【问题标题】:void* pointer returned from Function - Heap Corruption从函数返回的 void* 指针 - 堆损坏
【发布时间】:2012-03-14 17:26:53
【问题描述】:

以前,我只是使用 malloc 处理这些类型的 __out 函数参数,但我正在尝试改变我的方式。

作为一个具体的例子,在一个管理原始输入的类中,GetRawInputDeviceInfo()的原型是这样的:

UINT GetRawInputDeviceInfo(HANDLE, UINT, LPVOID, PUINT)

LPVOID 是指向包含我需要的信息的缓冲区的指针。 PUINT 是一个指向 UINT 的指针,该 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);

原始 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 的精神:)

【问题讨论】:

  • sizeof(&amp;cbSize) 将始终是 PUINT* 的大小,假设 32 位拱门为 4 个字节...因此您总是分配 4 个字节,可以吗?我不知道 *cbSize 应该是什么值。

标签: c++ c pointers void raii


【解决方案1】:

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);
    

您的示例代码不会导致堆损坏。可能您的真实代码使用了未初始化的buffer,这导致 GetRawInputDeviceInfo 将数据写入某个意外位置。

【讨论】:

  • 谢谢。这非常有效。我从中学到了很多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-20
  • 2020-05-03
  • 2020-06-11
  • 2017-01-18
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多