C# 在C中检查堆完整性和堆栈大小#

C# 在C中检查堆完整性和堆栈大小#,c#,stack,heap,C#,Stack,Heap,我正在试图追踪一个崩溃,当我强调我的C#代码并在低内存条件下运行时会发生这种情况。然而,在某些情况下,我的程序不会退出MemoryException,而是会崩溃并退出。这通常是由缓冲区溢出导致的内存损坏或堆栈溢出(或损坏)引起的 那么,有没有办法对堆的完整性进行检查,或者有没有办法检查线程上还有多少堆栈 出于速度的原因,我使用了很多不安全的代码,所以很可能我的代码在某个地方破坏了内存。不幸的是,崩溃是在损坏发生后随机发生的。我知道C#会在检测到缓冲区溢出时关闭应用程序,但有没有办法强迫它进行检查

我正在试图追踪一个崩溃,当我强调我的C#代码并在低内存条件下运行时会发生这种情况。然而,在某些情况下,我的程序不会退出MemoryException,而是会崩溃并退出。这通常是由缓冲区溢出导致的内存损坏或堆栈溢出(或损坏)引起的

那么,有没有办法对堆的完整性进行检查,或者有没有办法检查线程上还有多少堆栈

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


谢谢。

您可以使用以下方法处理这些情况:

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


当然,核证的排减量是非常严格的。你在他们身上做不了什么。它们是为代码的关键小部分而设计的。

在某些情况下,操作系统别无选择,只能删除流程。为了在进程中引发堆栈溢出或段错误之类的异常,内核必须在将控制权返回给进程之前,在发生故障的堆栈上写入异常记录。如果没有空间写这个记录,那么这个过程就会消失,你也无法阻止它。我所知道的两种情况是,如果在异常堆栈溢出后继续增长堆栈,或者无法提交保留堆栈页,这两种情况都非常罕见


你最好的办法是解决腐败问题。尝试在保护下运行。如果您知道异常发生的位置,请尝试在“调试器”下的缓冲区上设置“写时中断”中断点。或者试着在死后从写模式(例如可以是字符串)或从内存中搜索回缓冲区的引用来识别涂鸦者

在试图找出我的问题时,我发现这些文章非常有用:

最后一篇文章说:

如果无法为其分配内存 异常对象,运行时将 无一例外地终止 处理程序有执行的机会,这 很少会是理想的行为。 [因此,]而不是简单地拒绝 分配更多的内存,一个更温和的 更有效的方法是 允许少量内存增加,以便 可以成功创建异常对象 已创建,并且存在OutOfMemory异常 可以优雅地投掷和处理 托管代码

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


因此,我将实现文章中提到的技术,看看这是否解决了我的问题。不幸的是,它有点复杂,所以尝试起来不是一件很快的事情。

它会在没有显示任何异常的情况下退出吗?您是否尝试过在发行版和调试模式下编译和测试?您需要的是一个对话框,告诉您“未处理的异常”或“分段错误”或类似的信息,以提供线索。是的,它只是在没有任何异常的情况下退出。我已经在发布和调试模式下进行了测试。没有区别。如果使用stackalloc从堆栈中请求更多的内存,然后实际可用,则可能会出现类似的崩溃。也就是说,您不会得到堆栈溢出异常,程序只是退出。请注意,此崩溃仅在内存不足的情况下发生。因此,也许这毕竟不是腐败。可能是JIT的内存不足导致了这个退出。还要注意的是,我必须关闭虚拟内存的自动调整来强制内存不足的情况。换句话说,我真的强迫它耗尽内存。我正在阅读关于“受限执行区域”的文章,但我不认为这对我有什么帮助。这个问题使我的程序在代码中不可预知的地方崩溃,到处都是。我不能把我的整个计划变成CER。