代码之家  ›  专栏  ›  技术社区  ›  AZDean

检查C语言中的堆完整性和堆栈大小#

  •  3
  • AZDean  · 技术社区  · 15 年前

    我试图追踪一个崩溃,当我强调我的C代码和运行在低内存条件下。但是,在某些情况下,我的程序只是简单地崩溃和退出,而不是获取OutOfMeimyExtExchange。这通常是由于缓冲区溢出或堆栈溢出(或损坏)导致的内存损坏造成的。

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

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

    谢谢。

    3 回复  |  直到 15 年前
        1
  •  3
  •   Mehrdad Afshari    15 年前

    你可以通过使用 Constrained Execution Regions :

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

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

        2
  •  2
  •   AZDean    15 年前

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

    Investigating Memory Issues

    When memory is running low…

    IGCHost Interface

    Getting the most out of .NET by taking control

    最后一篇文章说:

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

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

    所以,我将实现那篇文章中提到的技术,看看这是否解决了我的问题。不幸的是,这有点复杂,所以这不是一个快速的尝试。

        3
  •  1
  •   Remus Rusanu    15 年前

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

    你最好的办法就是解决腐败问题。试着跑下去 gflags PageHeap 保护。如果您知道异常发生的位置,请尝试在调试器下的缓冲区上设置写入中断点。或者尝试从写模式(例如字符串)或从内存中搜索对缓冲区的引用来标识scribbler post-mortem。