3

我试图追踪当我强调我的 C# 代码并在低内存条件下运行时发生的崩溃。但是,在某些情况下,我的程序不会得到 OutOfMemoryException,而是会简单地崩溃并退出。这通常是由于缓冲区溢出或堆栈溢出(或损坏)造成的内存损坏。

那么,有没有办法检查堆的完整性,或者有没有办法检查线程上剩下多少堆栈?

出于速度原因,我使用了很多不安全的代码,所以很可能我的代码在某处损坏了内存。不幸的是,崩溃发生在损坏发生后的随机间隔。我知道 C# 在检测到缓冲区溢出时会关闭应用程序,但是有没有办法强制它进行检查?

谢谢。

4

3 回答 3

3

您可以使用约束执行区域来处理这些情况:

约束的执行区(CER) 是编写可靠托管代码的机制的一部分。CER 定义了一个区域,其中限制公共语言运行时 (CLR) 引发带外异常,这会阻止该区域中的代码完整执行。在该区域内,用户代码被限制执行会导致抛出带外异常的代码。该PrepareConstrainedRegions方法必须紧接在一个try块之前并标记catch, finally, 和fault块作为受约束的执行区域。一旦标记为受限区域,代码只能调用具有强可靠性契约的其他代码,并且代码不应分配或对未准备或不可靠的方法进行虚拟调用,除非代码已准备好处理故障。CLR 延迟在 CER 中执行的代码的线程中止。

当然,CER 的限制非常严格。你不能在他们身上做太多事情。它们专为关键的小部分代码而设计。

于 2009-10-28T15:28:37.023 回答
2

在试图追查我的问题时,我发现这些文章非常有帮助:

调查内存问题

当内存不足时……</a>

IGCHost 接口

通过控制充分利用 .NET

最后一篇文章说:

如果无法为异常对象分配内存,则运行时将终止而不给异常处理程序执行的机会,这很少是所需的行为。[所以,] 而不是简单地拒绝分配任何进一步的内存,一种更温和更有效的技术是允许少量内存增加,以便可以成功创建异常对象,并且可以由托管代码优雅地抛出和处理 OutOfMemory 异常。

我相信这是我需要做的以避免我的问题。因为我的应用程序非常占用内存,所以我不能让它将内存浪费到页面文件中,因为这非常非常慢。我需要我的应用程序将自身限制在物理内存中以保持性能可接受。但是当它确实内存不足时,我需要引发内存不足异常。我不能让应用程序崩溃!

因此,我将实施那篇文章中提到的技术,看看是否能解决我的问题。不幸的是,它有点复杂,因此尝试起来并不是一件容易的事。

于 2009-10-28T22:48:57.680 回答
1

在某些情况下,操作系统别无选择,只能抹杀该进程。为了在进程中引发堆栈溢出或段错误等异常,内核必须在将控制权交还给进程之前在错误堆栈上写入 EXCEPTION_RECORD。如果没有空间来写这个记录,那么这个过程就消失了,你无法做任何事情来阻止它。我知道这可能发生的两种情况是,如果您在 EXCEPTION_STACK_OVERFLOW 之后继续增长堆栈,或者如果无法提交保留的堆栈页面,这两种情况都非常罕见。

你最好的选择是修复腐败。尝试在gflags PageHeap保护下运行。如果您知道异常发生的位置,请尝试在调试器下的缓冲区上设置一个写时中断断点。或者尝试从写入模式(例如可以是字符串)或从内存中搜索返回到缓冲区的引用来识别涂鸦者事后分析。

于 2009-10-28T15:46:17.563 回答