void *指针从函数返回 - 堆腐败

时间:2012-03-14 17:26:53

标签: c++ c pointers void raii

以前,我只是使用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的精神:)

1 个答案:

答案 0 :(得分:3)

使用GetRawInputDeviceInfo的正确方法是

  1. 获取名称包含的字符数

    UINT char_count;
    GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, NULL, &char_count);
    
  2. 分配足够长的字符串缓冲区,并检索名称

    std::unique_ptr<wchar_t[]> buf (new wchar_t[char_count]);
    GetRawInputDeviceInfo(xxx.handle, RIDI_DEVICENAME, buf.get(), &char_count);
    
  3. 您的示例代码不会导致堆损坏。可能你的真实代码使用了未初始化的buffer,这导致GetRawInputDeviceInfo将数据写入某个非预期的位置。