tags:

views:

476

answers:

2

I'm working on a large, aging code base for an MFC app. The code has been worked on by many developers over time, and as a result, we have three different ways throughout the code of dealing with the possibility of an allocation failure with new.

The first way is to test for NULL on the result of new. We don't use nothrownew.obj so this is clearly an error that needs to be cleaned up.

The second is to catch CMemoryException* (yes, C++ exceptions are enabled in the compiler). From what I understand, MFC overrides the standard operator new, and throws this thing instead. I am fairly certain that this second method is correct in the MFC application itself. MFC overrides new, with its strange CMemoryException throwing version.

The last comes from our base of people who are good with C++, but aren't neccessarily MFC programmers. They are catching const std::bad_alloc&.

What I really don't know is what to expect for static libraries linked into the application. This is were the vast majority of the code that uses bad_alloc lives. Assuming these libraries are not compiled with MFC or ATL, and are written in standard C++ only, can they expect to catch bad_alloc? Or will the presence of MFC in the application they link to infect them with the global new operator and render their attempts to fail cleanly on a bad allocation moot?

If you have an answer, could you explain how this works, or point me to the right reference to sort this out?

+1  A: 

Congratulations -- you seem to have stumped all of us. :-)

In theory, if MFC provides an overload for the global new function, then it should be used by all code in the program. But since the static libraries were compiled without knowing about that, I can't say for certain that it would.

The best I can suggest is to write some test code to find out. (I won't have access to my Windows system for the next few hours, or I'd do so myself and give you an answer.)

Head Geek
This stumped my peers as well, and no one could come up with a good way to force new to fail without overloading new in the first place. Arg :)
christopher_f
+1  A: 

It will depend on the compile options for the static libraries to be linked to the application.

If the libraries are compiled with a configuration to use the static Standard C++ run-time then I would expect the operator new from the Standard C++ run-time to be called.

If libraries are compiled with a configuration to use the Standard C++ run-time DLL then the resolution of these functions will be delayed until program load and should be resolved to the MFC replacements of operator new.

I also included a link to this Herb Sutter article regarding handle allocation errors that you may find useful.

Henk
Thank you! We do link to the standard C++ runtime as a DLL, which means MFC exceptions for everyone. Unfortunately, one of the major targets of this app is a system without virtual memory, so allocation checking is required, ugh.
christopher_f
If your able to compile with symbols then I'd suggest stepping into the call to operator new and the debugger should prove definitively which implementation is being called. Not sure if that's helpful for your target platform tho..
Henk
Symbols are no problem. Forcing the branch to throw an exception, shows conclusively that CMemoryException* is being thrown. That complicates things a touch, but it's good to know what's really going on. Thanks again!
christopher_f