问题
Previously, I'd just dealt with these types of __out function parameters using malloc, but I'm trying to change my ways.
As a specific example, in a class to manage Raw Input, GetRawInputDeviceInfo() is prototyped as such:
UINT GetRawInputDeviceInfo(HANDLE, UINT, LPVOID, PUINT)
LPVOID is a pointer to a buffer containing the information I need. PUINT is a pointer to a UINT containing the size of data contained in the buffer pointed to by LPVOID.
Normally, I would (once I have populated the PUINT):
PUINT cbSize; // assume it is sized correctly and contains the proper
// length of data
LPVOID buffer = (LPVOID)malloc(sizeof(&cbSize));
GetRawInputDeviceInfo(XXX.handle, RIDI_DEVICENAME, buffer, cbSize);
//do something w/buffer
free(buffer);
Now, attempting to do this without malloc, I would write: (sorry, I'm typing this from work, so I may botch this from memory)
PUINT cbsize; // assume it is sized correctly and contains the proper
// length of data
1 of the following declaration and use examples: LPVOID unique_ptr:
std::unique_ptr<LPVOID> buffer;
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, buffer.get(),
cbSize);
UINT unique_ptr:
std::unique_ptr<UINT> buffer;
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME,
(LPVOID)buffer.get(), cbSize);
Raw UINT Pointer:
UINT *buffer = NULL;
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME,
(LPVOID)buffer, cbSize);
Then reading the buffer:
OutputDebugString((LPCSTR)buffer) //add .get() for unique_ptr
The thing is, the buffer contains the information I want, and it's outputted as it should be! However, when the unique_ptr goes out of scope and is deleted (or the UINT* is deleted), I get a Heap Corruption exception. I stepped through the code and what happens is once the GetRawInputDeviceInfo function runs, ALL of my class level containers/variables have their data rewritten. For example, the above sequence appears in a for loop, and my iterator goes from 0 (first iteration) to 80837436 (or so), and all other variables local variables are messed up.
So, how can I retrieve the information in the buffer without screwing everything else up? And preferably without using malloc/free, and with the spirit of RAII :)
回答1:
The correct way to use GetRawInputDeviceInfo is
Get the number of characters the name contains
UINT char_count; GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, NULL, &char_count);
Allocate a long enough string buffer, and retrieve the name
std::unique_ptr<wchar_t[]> buf (new wchar_t[char_count]); GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, buf.get(), &char_count);
Your example code won't cause heap corruption. Probably your real code uses an uninitialized buffer
, which caused GetRawInputDeviceInfo to write data to some unintended location.
来源:https://stackoverflow.com/questions/9706960/void-pointer-returned-from-function-heap-corruption