开发者

Free Allocated Memory Generates Exception - C++

开发者 https://www.devze.com 2023-01-28 01:01 出处:网络
There is a function in my application in which memory is allocated for formatting a port name.CreateFile is called to open the port.At the end of the function free is called to attempt to free the all

There is a function in my application in which memory is allocated for formatting a port name. CreateFile is called to open the port. At the end of the function free is called to attempt to free the allocated memory.

DWORD CSerialPort::Open( wchar_t * port )
{
    DCB dcb = {0};
    LPTHREAD_START_ROUTINE pThrea开发者_如何学编程dStart;
    void * pvThreadData = NULL;
    wchar_t * pwcPortName = NULL;
    DWORD dwRetVal = ERROR_SUCCESS;

    /* Validate parameters. */

    pwcPortName = (wchar_t *)malloc( wcslen( port ) + 6 );

    if ( pwcPortName == NULL )
    {
        TRACE(_T("CSerialPort::Open : Failed to allocate memory for formatted serial port name.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ERROR_NOT_ENOUGH_MEMORY, __WFILE__, __LINE__);
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    memcpy( pwcPortName, L"\\\\.\\", 4 * 2 );
    memcpy( pwcPortName + 4, port, wcslen( port ) * 2 + 2 );

    // Get a handle to the serial port.
    _hSerialPort = CreateFile(
        pwcPortName,                    // Formatted serial port
        GENERIC_READ | GENERIC_WRITE,   // Access: Read and write
        0,                              // Share: No sharing
        NULL,                           // Security: None
        OPEN_EXISTING,                  // OM port already exists
        FILE_FLAG_OVERLAPPED,           // Asynchronous I/O
        NULL                            // No template file for COM port
        );

    if ( _hSerialPort == INVALID_HANDLE_VALUE )
    {
        TRACE(_T("CSerialPort::Open : Failed to get the handle to the serial port.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
        return ::GetLastError();
    }

    /* Initialize the DCB structure with COM port parameters with BuildCommDCB. */

    /* Set the serial port communications events mask with SetCommMask. */

    /* Set serial port parameters with SetCommState. */

    /* Set the serial port communications timeouts with SetCommTimeouts. */

    /* Create thread to handle received data with CreateThread. */

    free( pwcPortName );                 // <-- Exception thrown here.

    return dwRetVal;
}

Can anyone tell me what I'm doing wrong? Thanks.


malloc allocates bytes, but you are using the allocated memory to store wchar_t.

You have to change the malloc size parameter to match your existing memcpy usage:

pwcPortName = (wchar_t *)malloc( wcslen( port ) + 6 );

should be

pwcPortName = (wchar_t *)malloc( (wcslen( port ) + 6) * sizeof(wchar_t));


Easier solution:

DWORD CSerialPort::Open( std::wstring const& port )
{
    // ...
    std::wstring portname = L"\\\\.\\" + port;

    // Get a handle to the serial port.
    _hSerialPort = CreateFile(
        portname.c_str(), // ...

Don't worry about freeing memory; C++ will now take care of that.


Try:

pwcPortName = (wchar_t *)malloc( sizeof(wchar_t) * (wcslen( port ) + 6) );

...because a wchar_t is two bytes in a unicode app. You'll have to make a similar change in your second memcpy call too.

But this being C++, you should use new and delete instead:

pwcPortName = new wchar_t[wcslen( port ) + 6];

//...

delete[] pwcPortName;


This would be neater:

DWORD CSerialPort::Open( wchar_t * port )
{
    DCB dcb = {0};
    LPTHREAD_START_ROUTINE  pThreadStart;
    void*     pvThreadData = NULL;
    DWORD     dwRetVal     = ERROR_SUCCESS;

    /* Validate parameters. */
    std::wstring  pwcPortName;

    pwcPortName.append(L"\\\\.\\");
    // memcpy( pwcPortName, L"\\\\.\\", 4 * 2 );
    //                                     ^^^ Whats this magic number? sizeof(wchar_t)
    //                                 ^^^ Is this one the size of the string?
    //                                     If you change the string you also need to
    //                                     modify the 4? Thats not good (hard to
    //                                     maintain (or should I say easy to break))
    pwcPortName.append(port);
    // memcpy( pwcPortName + 4, port, wcslen( port ) * 2 + 2 );
    //                      ^^^ Magic Number. Are you sure this is even correct?
    //                          Adding 4 to this moves the pointer 4 * sizeof(wchar_t)
    //                          So now you have an implied dependency on the above code
    //                          in this line. So if the string was changed you would need
    //                          to modify the 4 in two places!
    //                                               ^^^^^^^ * 2 + 2
    //                          Assume the * 2 is (* sizeof(wchar_t))
    //                          And the + 2 is (+ sizeof(wchar_t)) is to make sure
    //                          you copied the null terminator.                  

    // Get a handle to the serial port.
    _hSerialPort = CreateFile(
        pwcPortName.c_str(),            // Formatted serial port
        GENERIC_READ | GENERIC_WRITE,   // Access: Read and write
        0,                              // Share: No sharing
        NULL,                           // Security: None
        OPEN_EXISTING,                  // OM port already exists
        FILE_FLAG_OVERLAPPED,           // Asynchronous I/O
        NULL                            // No template file for COM port
        );


    // STUFF


    // No need to free the pointer as we used a std::Wstring to contain it
    // Thus it provides an exception safe memory leak free way of making sure
    // the memory is freeed.

    return dwRetVal;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消