tags:

views:

414

answers:

3

Hi, 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.

+3  A: 

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.

Mehrdad Afshari
A: 

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.

Remus Rusanu
+1  A: 

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.

AZDean