10
votes

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.

1
Do DLLs use a separate memory pool? stackoverflow.com/questions/10820114/…thang
And if so, can I purge it without requiring the application to unload the DLL? yeah, just delete the stuff from new and free the stuff from malloc.thang
Not having exception handling means that objects created on the stack (and inside a constructor that fails) will not be destroyed. If you are just going to exit when the bad_alloc happens, then you are fine with that, I suppose [as long a you don't have strange resources that don't get cleaned up with program exit - but most should]. If you are wanting to "continue" after bad_alloc, then the code will need to track objects and destroy all objects created in stack frames between the throw and catch. You can experiement by writing some small code that has printouts in destructors.Mats Petersson
@thang I meant get it deleted automatically. I use multiple third-party components, any of which may throw an OOM exception, so it would be nice to be able to deallocate any memory ever allocated from within my DLL (and kill any threads / close any file handles while we're at it). Statically linking the C runtime would increase binary size which is also not desirable.Nicolas Capens

1 Answers

1
votes

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.