如何诊断System.OutOfMemoryException?

soo*_*ise 6 c# out-of-memory

我在上周五离开工作之前运行了一些代码,我周一在这里,它以OutOfMemoryException停止.我估计整个过程需要进行数百亿次计算,所以这不是一项小任务.

我甚至不知道如何解决这个问题.
有什么指针吗?

asa*_*yer 9

Eric Lippert的这篇文章可能会有所帮助:"Out of Memory"不会引用物理内存


Jim*_*som 8

好吧,鉴于你提供的内容或缺乏,我只能在这里提供一些一般性的想法:首先,明显的答案是看看例外本身包含的信息,这应该给你一个想法你的代码分配失败的地方.

其次,您使用内存分析来更好地了解应用程序中发生的事情 - 我是dotTrace的用户,但可能有免费的替代品.

除了这个一般的adivce,您可能希望在您的问题中包含更多信息.您分配的是什么类型的对象,何时分配,是使用本机资源等.


Lir*_*ran 5

最简单,最直接的解决方案是:

  1. 使用procdump(包含在Sysinternals Suite中)在进程达到一些不合理的大小时进行完整的内存转储.
  2. 将转储加载到WinDbg中,并使用加载SOS调试扩展.loadby sos clr
  3. 使用以下命令:!dumpheap -stat以查看哪种类型的对象占用了大部分内存.
  4. 使用转储对象列表(泄漏类型) !dumpheap -type <MY_TYPE>
  5. 选择几个实例,然后发出命令:!gcroot <OBJ_ADDRESS>.输出应该告诉您哪个对象仍然包含对它的引用,以及为什么不释放该对象.

如果您怀疑泄漏的来源是一些原生代码,你可以通过发出以下命令来验证这一点:!eeheap -gc.输出将告诉您托管堆占用多少内存.如果你的进程的私有工作集大小远远大于托管堆的大小,那么你可能手上有本机泄漏(或者,也许是因为某种原因你产生了很多线程,所以你是由于线程的堆栈而耗尽空间[你可以通过发出这个命令检查你的进程中产生了多少线程:~*或者:!threads只显示被管理的线程].