ftd2xx: Memory corruption when calling FT_GetDeviceInfoList()

30 Views Asked by At

I am writing a c++ application in visual studio using the "ftd2xx" library provided by FTDI.

I try to retreive a list of all connected devices. So my application looks like this:

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

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

Now the nasty thing that is happening is, that when calling FT_GetDeviceInfoList(&devInfo, &index); the varialbe numDevices gets overwritten!

How could this happen?

And here is my "getDeviceList" function (and further below the header file):

// 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();
};

enter image description here

enter image description here

Appreciate any input!!

1

There are 1 best solutions below

0
Christian B. On

From https://www.ftdichip.com/Support/Knowledgebase/index.html?ft_getdeviceinfolist.htm :

FT_STATUS FT_GetDeviceInfo (FT_DEVICE_LIST_INFO_NODE *pDest, LPDWORD lpdwNumDevs) 

Parameters
*pDest Pointer to an array of FT_DEVICE_LIST_INFO_NODE structures.
lpdwNumDevs Pointer to the number of elements in the array. 

and the example states:

// allocate storage for list based on numDevs
devInfo = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*numDevs);

// get the device information list
ftStatus = FT_GetDeviceInfoList(devInfo,&numDevs);

Given the fact that devInfo is only "one" long, the raw access by FT_GetDeviceInfoList simple writes over the length of devInfo. My c++ is bit rusty and dated (pre 11) but this should fix the issue:

// ftdi.cpp
#include "ftdi.h"

std::vector<std::unique_ptr<FTDIDevice>> FTDIManager::getDeviceList() {
    std::vector<std::unique_ptr<FTDIDevice>> deviceList; //maybe shared_ptr is the better choice here. Have not used c++ for a long time.

    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;
    }

    std::vector<FT_DEVICE_LIST_INFO_NODE> devInfoArray(numDevices);
    ftStatus = FT_GetDeviceInfoList(devInfoArray.data(), &i);
    if (ftStatus == FT_OK) {
        for (auto &devInfo: devInfoArray) {
            // Create specific device object based on description or other criteria if needed
            auto device = std::make_unique<SpecificFTDIDevice>(devInfo.Description, devInfo.SerialNumber);
            deviceList.emplace_back(std::move(device));
        }
    }

    return std::move(deviceList);
}