【问题标题】:Debug and HeapAlloc调试和 HeapAlloc
【发布时间】:2016-06-29 21:21:12
【问题描述】:

在尝试处理 WinApi 中的堆时,HeapAlloc 的操作得到了一些奇怪的结果。让我们考虑以下代码。问题是,根据 Windows API 上的 Microsoft 文档(下一个 - Doc),我必须将两个 Success 字符串打印到控制台。当我尝试在 MSVC 2013 中使用Debud 选项运行此代码时,我得到一个Error。但最奇怪的是,当我尝试在没有Debug 选项的情况下运行此代码时,或者运行编译后的.exe 文件时,我得到了正确的结果。

#include <Windows.h>
#include <stdio.h>

int main()
{
    LPSYSTEM_INFO sys;
    HANDLE hNewHeap;
    LPVOID ptr;

    sys = (LPSYSTEM_INFO) HeapAlloc(GetProcessHeap(),
                                    0,
                                    sizeof(SYSTEM_INFO));
    GetSystemInfo(sys);
    printf("Page size: %u\n", sys->dwPageSize);//Here we get the 
    //'Page size: 4096' string
    //printed to the console


    hNewHeap = HeapCreate(0, 1, 1);
    //That's easy. We create new heap object, getting its HADNLE descriptor.
    //According to Doc, the initial heap size is set to page size, which is
    //4096 on my computer, like maximum heap size is also done. So the heap
    //size now is 4096.

    ptr = HeapAlloc(hNewHeap, 0, 2624); //Here we allocate the memory
    //block in our new heap, that might have 2624 bytes size.

    if ( ptr ) printf("Success!\n");//Here we check if the HeapAlloc functio
    //worked correctly and print the appropriate string.
    else printf("Error!\n");
    //On this time we get 'Success' string printed to the console and free
    //allocated memory block
    if ( ptr ) HeapFree(hNewHeap, 0, ptr);

    ptr = HeapAlloc(hNewHeap, 0, 2525);//Here we try to allocate the memory
    //block, which size is 2526. And, like previous time, we expect to get
    //'Success'.
    if ( ptr ) printf("Success!\n");
    else printf("Error!\n");
    //But we get 'Error' here!!!
    if ( ptr ) HeapFree(hNewHeap, 0, ptr);

    HeapDestroy(hNewHeap);
    system("pause");
};

如果您尝试使用任何小于 2624 的数字进行相同操作,您将不会收到“错误”。如果您尝试使用更多的 2625 号码执行此操作,您将收到“错误”。但是只有在 Debug 选项打开时我们才会收到“错误”。

谁能解释一下为什么会这样?

P.S.:抱歉英语不好。

PS:奇怪的是数字 2625 不对应任何功能或应用程序大小,有时我会得到正确的结果,即在重新启动工作室或对代码进行一些更改之后。(但只是有时)

【问题讨论】:

  • 检查 GetLastError()。
  • @KonstantinL 完成此操作并得到错误 8,它在 FormatMessage() 中具有下一个等效文本:“没有足够的存储空间来处理此命令。”
  • 而 HeapCreate(0, 1, 4097) 解决了这个问题?
  • @KonstantinL,确切地说。 HeapCreate(0, 4097, 1) 和 HeapCreate(0, 4097, 0) 也可以做到这一点。
  • 还有“系统使用私有堆中的内存来存储堆支持结构,因此并非所有指定的堆大小都可供进程使用。”在调试配置中,支持结构应该比在发布配置中需要更多空间。

标签: c windows winapi heap-memory


【解决方案1】:

您正在创建一个固定大小的堆。 documentation 说:

HeapCreate 函数将 dwMaximumSize 向上舍入为系统页面大小的倍数,然后在进程的虚拟地址空间中为堆保留该大小的块。

所以你的堆有 4096 字节的固定大小。

随后,您从此堆中的分配失败,因为堆不足以容纳正在分配的块。再次来自documentation

系统使用私有堆中的内存来存储堆支持结构,因此并非所有指定的堆大小都可供进程使用。例如,如果 HeapAlloc 函数从最大大小为 64K 的堆中请求 64 KB (K),则请求可能会因系统开销而失败。

正是这些堆支持结构引起了您的困惑。您认为堆中有足够的空间进行第二次分配,但您没有考虑堆支持结构。

HeapAlloc 的文档告诉您在失败时调用 GetExceptionCode。期望返回STATUS_NO_MEMORY

【讨论】:

  • 好。为什么第一次分配成功而第二次没有成功还有待解释。
  • 第一次分配有足够的内存。
  • 第二次分配
  • @Konst 你忽略了堆支持结构。
  • @Konst 不。没有人说 HeapAlloc/HeapFree 对将堆返回到之前的状态。使用堆足以改变它的状态。
猜你喜欢
  • 2013-01-02
  • 2012-01-03
  • 2013-01-16
  • 2010-10-26
  • 2019-10-02
  • 2011-10-21
  • 2019-05-25
  • 1970-01-01
相关资源
最近更新 更多