在试图处理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与任何函数或应用程序大小不对应,有时我得到正确的结果,即在重新启动工作室或对代码进行一些更改之后。(但有时只是)
答案 0 :(得分:0)
您正在创建固定大小的堆。 documentation说:
HeapCreate函数将dwMaximumSize四舍五入到系统页面大小的倍数,然后在进程的堆的虚拟地址空间中保留该大小的块。
所以你的堆的固定大小为4096字节。
随后,您从此堆的分配失败,因为堆不够大,无法分配块。再次来自documentation:
系统使用私有堆中的内存来存储堆支持结构,因此并非所有指定的堆大小都可用于进程。例如,如果HeapAlloc函数从最大大小为64K的堆中请求64千字节(K),则由于系统开销,请求可能会失败。
正是这些堆支持结构导致了您的困惑。您认为堆中有足够的空间用于第二次分配,但您没有考虑堆支持结构。
HeapAlloc
的文档告诉您在失败时致电GetExceptionCode
。期望返回STATUS_NO_MEMORY
。