Debug和HeapAlloc

时间:2016-03-14 17:33:55

标签: c windows winapi heap

在试图处理WinApi中的堆时,我对HeapAlloc的行为有一些奇怪的结果。让我们考虑以下代码。问题是根据Windows API上的Microsoft文档(下一个 - Doc),我必须在控制台上打印两个Success字符串。当我尝试在MSVC 2013中使用Error选项运行此代码时,我得到Debud。但最奇怪的是,当我尝试运行此代码时没有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与任何函数或应用程序大小不对应,有时我得到正确的结果,即在重新启动工作室或对代码进行一些更改之后。(但有时只是)

1 个答案:

答案 0 :(得分:0)

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

  

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

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

随后,您从此堆的分配失败,因为堆不够大,无法分配块。再次来自documentation

  

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

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

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