void* pointer returned from Function - Heap Corrup

2019-08-05 04:56发布

问题:

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

  1. Get the number of characters the name contains

    UINT char_count;
    GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, NULL, &char_count);
    
  2. 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.