我的应用程序中有一个函数,其中分配了内存以格式化端口名称。调用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;
}
谁能告诉我我做错了什么?感谢。
答案 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 ++ ,您应该使用new
和delete
代替:
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;
}