自由分配的内存生成异常 - C ++

时间:2010-12-01 15:30:40

标签: c++ visual-studio-2008 exception malloc free

我的应用程序中有一个函数,其中分配了内存以格式化端口名称。调用CreateFile来打开端口。在函数free结束时调用以尝试释放分配的内存。

DWORD CSerialPort::Open( wchar_t * port )
{
    DCB dcb = {0};
    LPTHREAD_START_ROUTINE pThreadStart;
    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;
}

谁能告诉我我做错了什么?感谢。

4 个答案:

答案 0 :(得分:7)

malloc分配字节,但您使用分配的内存来存储wchar_t

您必须更改malloc尺寸参数以匹配现有的memcpy用法:

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

应该是

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

答案 1 :(得分:4)

更简单的解决方案:

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

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

不要担心释放记忆; C ++现在将处理这个问题。

答案 2 :(得分:3)

尝试:

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

...因为wchar_t是unicode应用程序中的两个字节。您也必须在第二次memcpy来电时进行类似的更改。

但这是 C ++ ,您应该使用newdelete代替:

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

//...

delete[] pwcPortName;

答案 3 :(得分:1)

这将更整洁:

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