Visual C++ has a compiler setting "Enable C++ Exceptions" which can be set to "No". What exactly will happen if I set it this way? My code never explicitly throws or catches exceptions (and therefore the first thrown exception will terminate the program anyway) and doesn't rely on stack unwinding - should I expect any more undesired behaviour from the recompiled program?
If operator new
fails to allocate memory, I believe that it will return NULL
instead of throwing an std::bad_alloc
exception.
If you make any calls to third-party libraries that throw exceptions, much badness will result.
The MSDN documentation of the setting explains the different exception modes and even gives code examples to show the difference between the different modes. Furthermore, this article might be interesting, even though it's pretty old.
Bottom line: The option basically enables or disables the tracking of the life-spans of all your objects. Such tracking is required, because in the case of an exception, all the proper destructors need to be called, the stack has to be unwinded, and a lot of clean up is done. Such tracking requires organizational overhead (= additional code) - this can be dropped by setting the option to "No".
I haven't tried by myself, but it looks like you still can throw
and catch
exceptions if the option is set to "No", but the clean up and unwinding is missing, which might have very bad consequences (not recommended ;) ..
The compiler will omit the destructors and other stack-unwinding code that cleans up after C++ objects when they go out of scope as the result of an exception.
In other words, it leaves out a bunch of cleanup code. This will significantly improve performance, but also cause grave evil if an exception actually does get thrown. (Time it yourself if you don't believe me.)
The performance difference isn't really a reason to disable exceptions, except in certain critical applications where you will be absolutely obliged to do so.
When you say "NO" to "Enable C++ Exceptions" then Compiler's synchronous model of exception handling (/GX or /EHsc )is not chosen. In this mode, unwind semantics will not be enabled. That is , an object with automatic storage in the frame, between the function doing the throw and the function catching the throw, will not be destroyed.
You can refer MSDN or A Visual C++ Exception FAQ for more details on exception handling.
class Test
{
public:
Test()
{
printf("Test::constructor");
}
~Test()
{
printf("Test::Destructor");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int a;
try
{
Test a;
int* p = 0;
*p = 0; // Cause access violation
}
catch (...)
{
printf("Caught access violation");
}
return 0;
}
with No to exception handling the output would be:
Test::constructor
Caught access violation
You will still have access to Structured Exception Handling (SEH) which can be handled by __try, __except and __finally.
C++ exception handling is just a class implementation built on top of SEH.
The compiler will also complain if you try to instantiate classes within a function that has a SEH exception handler (complains about objects needing unwind, i.e. classes), which can be a bit messy, but there are ways to get around it.
As far as Standard C++ is concerned, you will get undefined behaviour. The C++ Standard does not admit the possibility of exceptions being turned off globally, and certain Standard Library operations are defined as throwing exceptions under certain circumstances.
The code I've worked with always turns off exceptions. I haven't seen issues of corruptions or resource trashing.
I'd thought that exceptions are generally kind of a bad fit with c++. The stack blasting, especially with lack of GC makes the whole exceptions thing a pain. And then the debate about what "exceptional" really means compared with just possibilities of failures.