1

I have a very serious problem with Embarcadero C++Builder 10.2.2 when compiling a mid-sized in-house application with the "classic" BCC32 compiler.

There's a class to wrap up some DLL functions responsible for reading the number of available hardware USB-interface boxes used for a connection interface and their serial numbers as string. The code below compiles without a flaw when using BCC32, as well as with BCC32c, but during runtime the BCC32 version crashes horribly, while everything works well with BCC32c.

The number of connected devices is sucessfully detected in both cases (which is 2 in my setup) but instead of returning the correct UsbDeviceSerialNo in

FDllPointers.GetUSBDeviceSN()

(for example 126739701012387721219679016621) there's only garbage in there:

��\x18.

In the second iteration of

for (unsigned int UsbDeviceNo = 0; UsbDeviceNo < 32; ++UsbDeviceNo)

there's an 'Access violation at address 00000000...' in the line

memset(UsbDeviceSerialNo, 0, SerNoBufferSize);

std::size_t TComUsbRoot::RefreshInterfaces()
{
    // Note:    This function does not work correctly when compiled
    //          with Borland BCC32 due to offset errors and AVs!!
    //          I don't have a clue, why this is the case at the moment.

    const unsigned int  SerNoBufferSize = 40;

    unsigned long       UsbDeviceMask = 0;
    char                UsbDeviceSerialNo[SerNoBufferSize];

    // Clear the current interfaces
    FInterfaces.clear(); // <-- std::vector<TComUsbInterface>

    // Get the currently available interface count
    int InterfaceCount = FDllPointers.GetAvailableUSBDevices(&UsbDeviceMask); // <-- int WINAPI CC_GetAvailableUSBDevices(unsigned long * DeviceMask); (from DLL)

    // We need at least one interface to proceed
    if (!InterfaceCount)
        return 0;

    // Check all USB device numbers
    for (unsigned int UsbDeviceNo = 0; UsbDeviceNo < 32; ++UsbDeviceNo)
    {
        // Check the USB device mask
        if (((1 << UsbDeviceNo) & UsbDeviceMask) != 0)
        {
            // Set the serial no to zeroes
            memset(UsbDeviceSerialNo, 0, SerNoBufferSize);

            // Get the USB device's serial number
            int Result = FDllPointers.GetUSBDeviceSN(
                            UsbDeviceNo,
                            UsbDeviceSerialNo,
                            SerNoBufferSize
                            );

            if (Result != 0)
            {
                throw Except(
                    std::string("ComUSB: Error while reading the USB device's serial number")
                    );
            }

            // Convert the serial number to wstring
            std::wstring SerialNo(CnvToWStr(UsbDeviceSerialNo));

            // Create a new interface object with the USB device's parameters
            TComUsbInterface Interface(
                *this,
                UsbDeviceNo,
                SerialNo,
                FDllPointers,
                FLanguage
                );

            // Add it to the vector
            FInterfaces.push_back(Interface);
        }
    }

    // Return the size of the interfaces vector
    return FInterfaces.size();
}

I simply don't know what's wrong here, as everything is allright with the new, Clang-based compiler. Unfortunately I cannot use the new compiler for this project, as the code completion (which is crappy and compiler-based in C++Builder and feels like using an early BETA edition of somtehing) makes the IDE crash 5 times an hour and the overall compilation time can be simply unbearable, even with the use of precompiled headers.

FlKo
  • 805
  • 1
  • 10
  • 27
  • try to define UsbDeviceNo berofe "for" – 2oppin Nov 01 '17 at 10:44
  • `TComUsbInterface` -- This better have correct copy semantics, otherwise putting this object in a vector would lead to undefined behavior. Also, is this function a `static` member function? If not, then the object that this function is a member of has to be valid, and there is no way to know this without a [mcve]. – PaulMcKenzie Nov 01 '17 at 10:56
  • Try to enable `CodeGuard` in the project options (Not sure if newer builders still got it however as I am stuck with old one) and compile&run the App. It should breakpoint on first detected error in your code (like accessing NULL pointer, overun/underrun arrays etc ...) It will reveal&log a lot of hidden errors. On big apps it could get out of memory easily in that case remove unnecessary parts of code for debugging) also the performance will drop considerably so be patient (My mid size apps starts around 30sec - 5 min) – Spektre Nov 08 '17 at 08:36
  • Also take a look at [bds 2006 C hidden memory manager conflicts](https://stackoverflow.com/a/18016392/2521214) the newer compilers should have it solved but you can use the `mmap` in case you do not have the CodeGuard option to identify memory leak problems. – Spektre Nov 08 '17 at 08:41

0 Answers0