C++ 线程在malloc和free虚拟大小中被阻塞

C++ 线程在malloc和free虚拟大小中被阻塞,c++,c,winapi,64-bit,C++,C,Winapi,64 Bit,我在WindowsServer2003Server(X64)上运行一个64位多线程程序,它遇到了一种情况,一些线程似乎永远被malloc或free函数阻塞。堆栈跟踪如下所示: ntdll.dll!NtWaitForSingleObject() + 0xa bytes ntdll.dll!RtlpWaitOnCriticalSection() - 0x1aa bytes ntdll.dll!RtlEnterCriticalSection() + 0xb040 bytes ntd

我在WindowsServer2003Server(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
顺便说一句,这里传递给新操作符的参数值不正确,可能是由于优化


同时,我在process Explorer中发现,该程序的虚拟大小为10GB,但专用字节和工作集非常小(Pageheap.exe检测到大多数与堆相关的错误-请尝试Pageheap


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

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


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

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

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

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

内存块的数量和大小取决于它们分配的调用堆栈,因此很容易看出最大的内存块在哪里

用户模式转储堆(UMDH)实用程序 与操作系统一起工作以 分析Windows堆分配以获得 具体过程


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

内存块的数量和大小取决于它们分配的调用堆栈,因此很容易看出最大的内存块在哪里

用户模式转储堆(UMDH)实用程序 与操作系统一起工作以 分析Windows堆分配以获得 具体过程

您的程序正在使用,这仅用于调试,并且会带来大量内存开销。若要查看哪些程序激活了PageHeap,请在命令行中执行此操作

% Gflags.exe /p
要在进程中禁用它,请键入以下内容(对于MyProg.exe):

您的程序正在使用,这仅用于调试,并且会带来大量内存开销。若要查看哪些程序激活了PageHeap,请在命令行中执行此操作

% Gflags.exe /p
要在进程中禁用它,请键入以下内容(对于MyProg.exe):


是的,我想这正是我的问题。我试图打开pageheap来解决这个问题,但后来发现它已经打开了。所以非常感谢!顺便说一句,你是通过我发布的调用堆栈发现的吗?我也没有意识到当页面打开时可能会发生这种副作用。是的,它在你的调用堆栈上(RtlpDebugPageHeapAllocate),大量保留虚拟地址空间的症状几乎证实了这一点:).Ya,我想这正是我的问题。我试图打开pageheap来解决这个问题,但后来发现它已经打开了。所以非常感谢!顺便说一句,你是通过我发布的调用堆栈找到这个的吗?我也没有意识到当页面打开时可能会发生这种副作用。是的,它在你的调用堆栈上(RtlpDebugPageHeapAllocate),大量保留虚拟地址空间的症状几乎证实了这一点:)。感谢您提供的大量信息。在我的情况下,malloc/free从未返回,我认为这可能是因为我在运行此程序之前意外启用了pageheap,因此引入的开销可能非常大,我猜最终malloc/free从未返回?感谢您提供的大量信息。我认为,在我的情况下,malloc/free从未返回这可能是因为我在运行这个程序之前意外地启用了pageheap,所以引入的开销可能非常大,我猜最终malloc/free不会返回?再更新一次,操作系统会弹出一个“虚拟内存不足”的弹出窗口当发生这种情况时。我想就像EmeryBerger说的,这是因为我在运行我的程序之前意外启用了pageheap。感谢大家提供的大量信息,非常感谢!再更新一次,操作系统确实会弹出一个“虚拟内存不足”的弹出窗口当发生这种情况时。我想就像EmeryBerger说的,这是因为我在运行我的程序之前意外地启用了pageheap。感谢大家提供的大量信息,非常感谢!
% Gflags.exe /p /disable MyProg.exe