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

发布于 2024-08-09 00:50:39 字数 286 浏览 7 评论 0原文

我试图找出当我对 C# 代码施加压力并在低内存条件下运行时发生的崩溃。但是,在某些情况下,我的程序不会出现 OutOfMemoryException,而是会崩溃并退出。这通常是由于缓冲区溢出导致的内存损坏或堆栈溢出(或损坏)引起的。

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

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

谢谢。

I'm trying to track down a crash that happens when I stress my C# code and run in low memory conditions. However, in some cases, instead of getting OutOfMemoryException, my program will simply crash and exit. This is usually caused by memory corruption from overrunning a buffer or because of stack overflow (or corruption).

So, is there a way to run a check on the heap's integrity, or is there a way to check how much stack is left on a thread?

I use lots of unsafe code for speed reasons, so it is quite likely I have code corrupting memory somewhere. Unfortunately, the crash happens at random intervals after the corruption happens. I understand C# will close down a app when it detects buffer overruns, but is there a way to force it to do a check?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紫瑟鸿黎 2024-08-16 00:50:39

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

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


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

You can handle those situations by using Constrained Execution Regions:

A constrained execution region (CER) is part of a mechanism for authoring reliable managed code. A CER defines an area in which the common language runtime (CLR) is constrained from throwing out-of-band exceptions that would prevent the code in the area from executing in its entirety. Within that region, user code is constrained from executing code that would result in the throwing of out-of-band exceptions. The PrepareConstrainedRegions method must immediately precede a try block and marks catch, finally, and fault blocks as constrained execution regions. Once marked as a constrained region, code must only call other code with strong reliability contracts, and code should not allocate or make virtual calls to unprepared or unreliable methods unless the code is prepared to handle failures. The CLR delays thread aborts for code that is executing in a CER.

Of course, CERs are very restrictive. You can't do much in them. They are designed for critical small parts of code.

小猫一只 2024-08-16 00:50:39

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

调查内存问题

当内存不足时...

IGCHost 接口

< a href="http://www.dotnetperformance.com/downloads/hosting.doc" rel="nofollow noreferrer">通过控制来充分利用 .NET

上一篇文章内容如下:

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

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

因此,我将实施该文章中提到的技术,看看是否可以解决我的问题。不幸的是,它有点复杂,所以尝试起来并不容易。

While trying to track down my problem, I found these articles were very helpful:

Investigating Memory Issues

When memory is running low…

IGCHost Interface

Getting the most out of .NET by taking control

The last article says the following:

If memory cannot be allocated for
exception objects, the runtime will
terminate without giving exception
handlers a chance to execute, which
will rarely be the desired behaviour.
[So,] rather than simply refusing to
allocate any further memory, a gentler
and more effective technique is to
allow a small memory increase so
exception objects can be successfully
created, and an OutOfMemory exception
can gracefully thrown and handled by
managed code.

I believe this is what I need to do to avoid my issue. Because my app is very memory intensive, I cannot afford to let it trash memory to a paging file, as that is VERY, VERY slow. I need my app to limit itself to physical memory to keep performance acceptable. But when it does run out of memory, I need an out-of-memory exception raised. I CAN'T have the app simply crash!

So, I will implement the technique mentioned in that article and see if that solves my problem. Unfortunately, it's a bit complicated, so it's not a quick thing to try out.

時窥 2024-08-16 00:50:39

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

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

There are certain conditions when the OS has no choice but to obliterate the process. In order to raise an exception like stack overflow or segment fault in a process, the kernel must write an EXCEPTION_RECORD on the faulting stack before it gives control back to the process. If there is no room to write this record then the process just vanishes and there isn't anything you can do to stop it. The two situations I know of this can happen is if you continue to grow the stack after a EXCEPTION_STACK_OVERFLOW or if a reserved stack page cannot be committed, both being quite rare situations.

Your best bet would be to fix the corruption. Try running under gflags PageHeap protection. If you know the place where the exception occurs, try setting a break-on-write break point on the buffer under debugger. Or try to identify the scribbler post-mortem, from the write pattern (could be a string for instance) or from searching the memory for references back to your buffer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文