[英]Threads are blocked in malloc and free, virtual size
我在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來解決此問題。
之前有沒有人有類似的經驗? 您能和我分享一下,以便我得到更多提示嗎?
非常感謝!
您的程序使用的是PageHeap ,它僅用於調試,並且會占用大量內存。 若要查看哪些程序已激活PageHeap,請在命令行中執行此操作。
% Gflags.exe /p
要為您的進程禁用它,請鍵入以下命令(對於MyProg.exe):
% Gflags.exe /p /disable MyProg.exe
Pageheap.exe檢測到大多數與堆相關的錯誤-嘗試Pageheap
您還應該查看“將參數值傳遞給新的...”-這種損壞是否在調試模式下發生? 確保禁用所有優化。
如果系統內存不足,則可能是操作系統正在交換,這意味着對於單個分配,在最壞的情況下,操作系統可能需要找到最佳交換對象,將其免費寫入磁盤內存並返回。 您確定它正在鎖定還是性能可能很慢? 當這兩個線程等待對malloc/free
的調用完成時,是否可以將另一個線程交換內存到磁盤?
我的首選解決方案是調試本機應用程序中的泄漏,以使用UMDH獲取進程中用戶模式堆的連續快照,然后再次運行UMDH來區分快照。 快照中的任何更改模式都可能泄漏。
您可以通過分配的調用堆棧來了解存儲塊的數量和大小,因此可以很容易地看出最大的存儲空間在哪里。
用戶模式轉儲堆(UMDH)實用程序可與操作系統一起使用,以分析特定進程的Windows堆分配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.