以前,我只是使用malloc处理这些类型的__out函数参数,但我正在尝试改变我的方式。
作为一个具体的例子,在一个管理Raw Input的类中,GetRawInputDeviceInfo()原型如下:
UINT GetRawInputDeviceInfo(HANDLE, UINT, LPVOID, PUINT)
LPVOID是指向包含我需要的信息的缓冲区的指针。 PUINT是一个指向UINT的指针,其中包含LPVOID指向的缓冲区中包含的数据大小。
通常,我会(一旦我填充了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);
现在,尝试在没有malloc的情况下这样做,我会写: (对不起,我是从工作中输入的,所以我可能会把它从内存中删除)
PUINT cbsize; // assume it is sized correctly and contains the proper
// length of data
以下1个声明和使用示例: 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指针:
UINT *buffer = NULL;
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME,
(LPVOID)buffer, cbSize);
然后阅读缓冲区:
OutputDebugString((LPCSTR)buffer) //add .get() for unique_ptr
问题是,缓冲区包含我想要的信息,并按原样输出!但是,当unique_ptr超出范围并被删除(或UINT *被删除)时,我会收到堆损坏例外。我逐步完成了代码,一旦GetRawInputDeviceInfo函数运行,会发生什么,我的所有类级容器/变量都重写了它们的数据。例如,上面的序列出现在for循环中,我的迭代器从0(第一次迭代)变为80837436(左右),所有其他变量局部变量都搞砸了。
那么,如何在不搞砸其他所有内容的情况下检索缓冲区中的信息呢?并且最好不使用malloc / free,并且具有RAII的精神:)
答案 0 :(得分:3)
使用GetRawInputDeviceInfo的正确方法是
获取名称包含的字符数
UINT char_count;
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, NULL, &char_count);
分配足够长的字符串缓冲区,并检索名称
std::unique_ptr<wchar_t[]> buf (new wchar_t[char_count]);
GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, buf.get(), &char_count);
您的示例代码不会导致堆损坏。可能你的真实代码使用了未初始化的buffer
,这导致GetRawInputDeviceInfo将数据写入某个非预期的位置。