.net 保留内存是否会导致内存不足异常

.net 保留内存是否会导致内存不足异常,.net,memory,memory-management,out-of-memory,windbg,.net,Memory,Memory Management,Out Of Memory,Windbg,我们有一个32位的windows服务泄漏内存-抛出OutOfMemory异常。它是在windows server 2003上运行的.net 4.0可执行文件。在使用WinDbg调试崩溃转储文件时,我发现大部分内存实际上是保留的,没有提交。 从WinDbg屏幕截图可以看出,有2.5 Gb的未分类内存使用,其中大部分2.1 Gb实际上是保留内存(MEM_RESERVE)。我有调试crush转储的经验,但这种情况对我来说是新的。MEM_提交退出正常-564.270 Mb,托管堆大小约为82 Mb

我们有一个32位的windows服务泄漏内存-抛出OutOfMemory异常。它是在windows server 2003上运行的.net 4.0可执行文件。在使用WinDbg调试崩溃转储文件时,我发现大部分内存实际上是保留的,没有提交。

从WinDbg屏幕截图可以看出,有2.5 Gb的未分类内存使用,其中大部分2.1 Gb实际上是保留内存(MEM_RESERVE)。我有调试crush转储的经验,但这种情况对我来说是新的。MEM_提交退出正常-564.270 Mb,托管堆大小约为82 Mb

我还检查了本机堆,查看是否保存了大量数据,但也没有发现任何可疑的内容

所以我的问题是-MEM_RESERVED是否可能导致OOM异常?如果是这样,我如何调试它,看看为什么/有多大的内存被保留?你还会去哪里寻找可能的问题


如果需要任何其他信息,请询问,我将更新我的帖子。

是的,保留内存会触发
OutOfMemoryException
。尝试分配两个非常大的字节数组。在写入数组内容之前,不会提交这些数组的内存。但是,只需分配这些数组,就可以轻松触发OOM


我不知道具体的实现细节,但由于VirtualAlloc如果不能满足保留请求就会失败,因此我假设CLR会将其转换为异常。我不知道如何将失败的保留请求变成有用的东西,因此异常是一个明智的选择。

如果系统无法为应用程序分配更多虚拟内存,则会发生OutOfMemoryException。保留内存是虚拟内存,因此会达到该限制

<>你可以在C++中最容易地尝试:

while(::VirtualAlloc(NULL, 65536, MEM_RESERVE, PAGE_READWRITE) != NULL );
std::cout << "All memory reserved. Now check with tools." << std::endl;
但是,VirtualAlloc()不在堆上分配内存,因此
!堆
在这种情况下不有用,只显示默认的进程堆:

0:000> !heap
Index   Address  Name      Debugging options enabled
  1:   00440000 
相反,heap mamanger使用VirtualAlloc()获取内存。还要注意,.NET也不使用堆管理器。它还使用VirtualAlloc()直接分配内存,然后自行管理。所以,因为您可以在
的输出中看到它!堆
这不是.NET问题,而是本机内存问题


在我的天真理解中,
gflags
设置应该有助于确定堆分配的源。但是,我希望命令
!heap-t
只会显示分配内存但未实现的DLL的名称

感谢您的回复,您是否知道我怎样才能看到WinDbg中保留了这么大的内存?假设内存由托管对象使用,您可以使用
检查这些!转储堆
!执行
。然而,考虑到
的输出!eeheap
显示托管堆很小,我假设有其他东西保留了此内存。请指定其他什么可以保留内存?我很困惑,因为我认为“某物”要么在托管堆上,要么在本机堆上有一些本机资源——它们都没有指向任何可疑的东西。还有什么可以保留内存?我很乐意马上查一查。我说的别的意思是“本地人”。正如我所说,如果保留内存支持托管对象,那么您将能够在托管堆上找到这些对象。因为本机库或运行时本身似乎不是这种情况,但我不能肯定。通过查看
的输出,您可以获得有关CLR分配的一些附加信息!eeheap
。感谢您的输入。我试过了!heap-t命令,但它没有提供任何有用的信息。我正在努力挖掘本地记忆,看看能在那里找到什么。任何其他检查其他内容的建议都是非常受欢迎的。
0:000> !heap
Index   Address  Name      Debugging options enabled
  1:   00440000