Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure out-of-memory robustness with C++ exceptions disabled (VS2010)?

I'm working on a performance-critical dynamically-linked library (DLL) that should also have a relatively small binary size. Since it doesn't explicitly throw any exceptions, I'd like to disable exception support altogether. However, there's one exception (pun unintended): when running out of memory (OOM), I have to report an error code to the application so it has a chance to handle things gracefully. The code base is too large to check every allocation individually and propagate the error, and contains external code that I shouldn't touch. So I'd like to catch OOM exceptions in my DLL's exported functions.

A quick test shows that when disabling C++ exceptions in Visual C++ 2010 (i.e. no /EHa, /EHsc or /EHs flags), it still jumps to a catch(std::bad_alloc&) block when allocating too much memory.

So it seems to work as desired. However, I get the following level 1 warning: "C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc". MSDN says that "an object with automatic storage in the frame, between the function doing the throw and the function catching the throw, will not be destroyed".

Exactly what would I lose here? It's fine to leave things in an undefined state, as long as anything that was created through the library can be deleted, and the application can start over again (if it so chooses). Is there a big risk of leaking memory that cannot be recovered?

Do DLLs use a separate memory pool? And if so, can I purge it without requiring the application to unload the DLL? I can easily make my library ignore any further (exported) function calls until the application performs a reinitialization.

Thanks for your advice.

like image 504
Nicolas Capens Avatar asked Feb 06 '13 17:02

Nicolas Capens


1 Answers

A few preliminaries:

I don't know if throwing an exception without exception handling enabled is undefined behavior or not by the standard, but you are certainly not going to get stack unwinding/destructor calls from your objects on the stack.

If you are writing C++ style code using RAII for mutexes, files, memory, etc, this is a Very Bad Thing.

Moving on then, and assuming your code is essentially C-style code:

1) If you are statically linking to the C runtime library, your DLL will not share a heap with your main application. Unloading the DLL should release the leaked memory -- but again, have a care about other resources.

2) If you are dynamically linking to the C runtime (quite common), then you are sharing a heap. You will have to have a way to manually release any memory allocated from the DLL.

Having myself mucked around far too much with DLL boundary issues, I would recommend a quick benchmarking to see what you're paying for in terms of leaving exceptions enabled. Depending on your platform and compiler, unthrown exceptions can have a quite negligible performance impact.

like image 123
Stephen Avatar answered Oct 19 '22 03:10

Stephen