You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ftd2xx调用FT_GetDeviceInfoList()时内存损坏问题求助

问题:调用FT_GetDeviceInfoList时numDevices被意外覆盖

我在Visual Studio中使用FTDI提供的ftd2xx库编写C++应用,尝试获取所有已连接设备的列表。但调用FT_GetDeviceInfoList(&devInfo, &i)时,numDevices变量被意外覆盖。以下是相关代码:

Application.cpp

int main()
{
    std::cout << "My FTDI finder!\n";

    FTDIManager ftdiManager;
    std::vector<FTDIDevice*> deviceList = ftdiManager.getDeviceList();
    ...
}

ftdi.cpp

#include "ftdi.h"

std::vector<FTDIDevice*> FTDIManager::getDeviceList() {
    std::vector<FTDIDevice*> deviceList;

    FT_STATUS ftStatus;
    DWORD numDevices;
    ftStatus = FT_CreateDeviceInfoList(&numDevices);
    if (ftStatus != FT_OK) {
        std::cerr << "Error: FT_CreateDeviceInfoList failed with status " << ftStatus << std::endl;
        return deviceList;
    }

    for (DWORD i = 0; i < numDevices; ++i) {
        FT_DEVICE_LIST_INFO_NODE devInfo;

        ftStatus = FT_GetDeviceInfoList(&devInfo, &i);
        if (ftStatus == FT_OK) {
            std::string description = reinterpret_cast<const char*>(devInfo.Description);
            std::string serial = reinterpret_cast<const char*>(devInfo.SerialNumber);
            // Create specific device object based on description or other criteria if needed
            FTDIDevice* device = new SpecificFTDIDevice(description, serial);
            deviceList.push_back(device);
        }
    }

    return deviceList;
}

ftdi.h

#include <ftd2xx.h>
#include <vector>

class FTDIDevice {
public:
    FTDIDevice(const std::string& description, const std::string& serial) : description(description), serial(serial) {}

    std::string getDescription() const { return description; }
    std::string getSerial() const { return serial; }

    virtual std::string getDeviceName() const = 0; // Pure virtual function to get device name

private:
    std::string description;
    std::string serial;
};


class SpecificFTDIDevice : public FTDIDevice {
public:
    SpecificFTDIDevice(const std::string& description, const std::string& serial) : FTDIDevice(description, serial) {}

    std::string getDeviceName() const override {
        // Implement device-specific functionality to get the name
        return "Specific Device Name";
    }
};


class FTDIManager {
public:
    FTDIManager() {}
    ~FTDIManager() {}

    std::vector<FTDIDevice*> getDeviceList();
};

问题原因分析

核心问题是对FT_GetDeviceInfoList函数的参数用法理解错误:

  • 该函数的第二个参数是输入输出型参数:输入时表示你提供的缓冲区能容纳的设备数量,输出时表示实际返回的设备数量(或所需的缓冲区大小)。
  • 你的代码中,循环里将循环变量i的地址传入该参数,当函数检测到你只提供了1个FT_DEVICE_LIST_INFO_NODE的缓冲区(远小于实际设备数numDevices)时,会将所需的缓冲区大小(即numDevices)写入i,导致循环变量i被直接修改为numDevices,循环条件i < numDevices瞬间不成立,循环提前终止。这会让你误以为是numDevices被覆盖,实际是循环变量被篡改。
  • 此外,由于缓冲区不足,FT_GetDeviceInfoList会返回FT_INSUFFICIENT_BUFFER错误,你的代码忽略了这种错误情况,导致设备信息根本无法正确获取。

解决办法

正确的做法是一次性获取所有设备的信息,而非循环调用FT_GetDeviceInfoList。修改后的getDeviceList函数如下:

std::vector<FTDIDevice*> FTDIManager::getDeviceList() {
    std::vector<FTDIDevice*> deviceList;

    FT_STATUS ftStatus;
    DWORD numDevices;
    ftStatus = FT_CreateDeviceInfoList(&numDevices);
    if (ftStatus != FT_OK) {
        std::cerr << "Error: FT_CreateDeviceInfoList failed with status " << ftStatus << std::endl;
        return deviceList;
    }

    // 如果没有设备,直接返回空列表
    if (numDevices == 0) {
        return deviceList;
    }

    // 分配足够大小的缓冲区存储所有设备信息
    std::vector<FT_DEVICE_LIST_INFO_NODE> devInfoList(numDevices);
    ftStatus = FT_GetDeviceInfoList(devInfoList.data(), &numDevices);
    if (ftStatus != FT_OK) {
        std::cerr << "Error: FT_GetDeviceInfoList failed with status " << ftStatus << std::endl;
        return deviceList;
    }

    // 遍历所有设备信息,创建对应的FTDIDevice对象
    for (DWORD i = 0; i < numDevices; ++i) {
        const FT_DEVICE_LIST_INFO_NODE& devInfo = devInfoList[i];
        std::string description(reinterpret_cast<const char*>(devInfo.Description));
        std::string serial(reinterpret_cast<const char*>(devInfo.SerialNumber));
        FTDIDevice* device = new SpecificFTDIDevice(description, serial);
        deviceList.push_back(device);
    }

    return deviceList;
}

关键修改点:

  1. 获取设备数量后,直接分配包含numDevices个FT_DEVICE_LIST_INFO_NODE的向量作为缓冲区。
  2. 调用FT_GetDeviceInfoList时,传入缓冲区首地址和numDevices的地址:输入的numDevices是缓冲区大小,输出的numDevices是实际读取到的设备数。
  3. 遍历缓冲区中的所有设备信息,逐个创建FTDIDevice对象,避免循环调用函数导致的参数篡改问题。

内容的提问来源于stack exchange,提问作者RadioMan85

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:27:06