线程在malloc和free虚拟大小中被阻止

时间:2011-01-12 07:24:45

标签: c++ c winapi 64-bit

我在Windows Server 2003服务器(X64)上运行64位多线程程序,遇到一些线程似乎在malloc或free函数中被永久阻塞的情况。堆栈跟踪如下:

ntdll.dll!NtWaitForSingleObject()  + 0xa bytes  
ntdll.dll!RtlpWaitOnCriticalSection()  - 0x1aa bytes    
ntdll.dll!RtlEnterCriticalSection()  + 0xb040 bytes 
ntdll.dll!RtlpDebugPageHeapAllocate()  + 0x2f6 bytes    
ntdll.dll!RtlDebugAllocateHeap()  + 0x40 bytes  
ntdll.dll!RtlAllocateHeapSlowly()  + 0x5e898 bytes  
ntdll.dll!RtlAllocateHeap()  - 0x1711a bytes    
MyProg.exe!malloc(unsigned __int64 size=0)  Line 168    C
MyProg.exe!operator new(unsigned __int64 size=1)  Line 59 + 0x5 bytes   C++


ntdll.dll!NtWaitForSingleObject()   
ntdll.dll!RtlpWaitOnCriticalSection()   
ntdll.dll!RtlEnterCriticalSection()     
ntdll.dll!RtlpDebugPageHeapFree()   
ntdll.dll!RtlDebugFreeHeap()    
ntdll.dll!RtlFreeHeapSlowly()   
ntdll.dll!RtlFreeHeap()     
MyProg.exe!free(void * pBlock=0x000000007e8e4fe0)   C
顺便说一句,传递给新运算符的参数值在这里可能不正确,可能是由于优化。

另外,与此同时,我发现在进程资源管理器中,该程序的虚拟大小为10GB,但私有字节和工作集非常小(<2GB)。我们确实有一些线程使用virtualalloc但是以一种在调用中提交内存的方式,并且这些线程没有被阻塞。

m_pBuf = VirtualAlloc(NULL, m_size, MEM_COMMIT, PAGE_READWRITE);
......
VirtualFree(m_pBuf, 0, MEM_RELEASE);

这对我来说很奇怪,似乎有很多虚拟空间被保留但未提交,而malloc / free被锁定。我猜测内存/对象是否有任何损坏,所以计划打开带有pageheap的gflag来解决这个问题。

之前有没有人有类似的经历?你能跟我分享一下吗?我可能会得到更多提示吗?

非常感谢!

4 个答案:

答案 0 :(得分:2)

您的程序正在使用PageHeap,它仅用于调试并且会产生大量内存开销。要查看已激活PageHeap的程序,请在命令行执行此操作。

% Gflags.exe /p

要为您的进程禁用它,请键入此内容(对于MyProg.exe):

% Gflags.exe /p /disable MyProg.exe

答案 1 :(得分:1)

Pageheap.exe检测到大多数与堆相关的错误 - 尝试Pageheap

此外,您应该查看“传递给新...的参数值” - 在调试模式下是否会发生此损坏?确保禁用所有优化。

答案 2 :(得分:1)

如果你的系统内存不足,可能是操作系统交换的情况,这意味着对于单个分配,在最坏的情况下,操作系统可能需要找到交换的最佳候选者,将其写入磁盘,释放内存并将其返回。你确定它是锁定的还是只是表现得很慢?另外一个线程可以将内存交换到磁盘,而这两个线程等待它调用malloc/free来完成吗?

答案 3 :(得分:1)

我在本机应用程序中调试泄漏的首选解决方案是使用UMDH获取进程中用户模式堆的连续快照,然后再次运行UMDH以区分快照。快照中的任何变化模式都可能是泄漏。

你可以通过分配调用堆来获得内存块的计数和大小,因此可以非常直接地查看最大的生猪位置。

  

用户模式转储堆(UMDH)实用程序   与操作系统一起使用   分析a的Windows堆分配   具体过程。