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; }
关键修改点:
- 获取设备数量后,直接分配包含
numDevices个FT_DEVICE_LIST_INFO_NODE的向量作为缓冲区。 - 调用
FT_GetDeviceInfoList时,传入缓冲区首地址和numDevices的地址:输入的numDevices是缓冲区大小,输出的numDevices是实际读取到的设备数。 - 遍历缓冲区中的所有设备信息,逐个创建
FTDIDevice对象,避免循环调用函数导致的参数篡改问题。
内容的提问来源于stack exchange,提问作者RadioMan85
相关产品推荐
相关产品推荐

