检查 C# 中的堆完整性和堆栈大小
我试图找出当我对 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用受限执行区域来处理这些情况:
当然,CER 的限制非常严格。你不能在其中做太多事情。它们是为代码的关键小部分而设计的。
You can handle those situations by using Constrained Execution Regions:
Of course, CERs are very restrictive. You can't do much in them. They are designed for critical small parts of code.
在尝试找出我的问题时,我发现这些文章非常有帮助:
调查内存问题
当内存不足时...
IGCHost 接口
< a href="http://www.dotnetperformance.com/downloads/hosting.doc" rel="nofollow noreferrer">通过控制来充分利用 .NET
上一篇文章内容如下:
我相信这是我需要做的,以避免我的问题。因为我的应用程序非常占用内存,所以我不能让它将内存浪费到分页文件中,因为那非常非常慢。我需要我的应用程序将自身限制为物理内存,以保持可接受的性能。但是当它确实耗尽内存时,我需要引发内存不足异常。我不能让应用程序崩溃!
因此,我将实施该文章中提到的技术,看看是否可以解决我的问题。不幸的是,它有点复杂,所以尝试起来并不容易。
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:
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.
在某些情况下,操作系统别无选择,只能删除该进程。为了在进程中引发堆栈溢出或段错误等异常,内核必须在将控制权交还给进程之前在错误堆栈上写入 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.