I'm reading the book Inside the C++ Object Model and I got a paragraph as below:
There are a number of drawbacks to using statically initialized
objects. For example, if exception handling is supported, these
objects cannot be placed within try blocks. This can be particularly
unsatisfactory with statically invoked constructors because any throw
will by necessity trigger the default terminate() function within the
exception handling library.
If I get it correctly, it means that
MyGlobalObject obj;
int main()
{
try
{
// do something with obj here is unsatisfactory
}
catch(...){}
return 0;
}
is not good. But I don't know why. Why any throw will be necessity trigger the default terminate() function.
What it means is you can't catch exceptions from statically initialized objects because they are initialized before main() starts making it impossible to surround them with a try{} block.
MyGlobalObject obj; // this initializes before main() starts
int main()
{
try
{
// too late to protect the static initialized global
// with this try block during its initialization
// but any operations you perform on it afterwards
// inside this try{} block will be fine.
}
catch(std::exception const& e)
{
}
}
One solution to this is to put the static objects in a function like this:
MyGlobalObject& get_my_global_object()
{
// This will not initialize until this function
// is called for the first time.
static MyGlobalObject obj;
return obj;
}
int main()
{
try
{
// now if the global object throws during its
// initializatin the exception will be caught.
MyGlobalObject& obj = get_my_global_object();
}
catch(std::exception const& e)
{
}
}
Related
I would like my C++ code to stop running with proper object cleanup if a certain condition is met; in a constructor of a class.
class A {
public:
int somevar;
void fun() {
// something
}
};
class B {
public:
B() {
int possibility;
// some work
if (possibility == 1) {
// I want to end the program here
kill code;
}
}
};
int main() {
A a;
B b;
return 0;
}
How can I terminate my code at that point doing proper cleanup. It's known that, std::exit does not perform any sort of stack unwinding, and no alive object on the stack will call its respective destructor to perform cleanup. So std::exit is not a good idea.
You should throw an exception, when the constructor fails, like this:
B() {
if(somethingBadHappened)
{
throw myException();
}
}
Be sure to catch exceptions in main() and all thread entry functions.
Read more in Throwing exceptions from constructors. Read about Stack unwinding in How can I handle a destructor that fails.
It is not possible to perform just from a constructor. If you throw an exception then applications need to set up a proper exception handling code at entry points, because if you just thrown an exception that won't be handled then compiler is allowed to skip stack unwinding and cleanup.
If you don't want to use use exceptions, you can have an init method in class B that returns a return code:
class B {
public:
B(/*parameters that will be used by init*/) : ...
int init(); // actually initialize instance and return non 0 upon failure
}
I have some library (actually the tbb library compiled with a different compiler), throwing an exception before main() proper started. Is there a way to catch that?
int main() { std::cout << "Hello World" << std::endl; }
gives
terminating with unexpected foreign exception
Abort (core dumped)
if I link against said library (which is not used in this example, but in other code it will be).
Generally speaking, it is not possible in standard C++ to catch an exception that is thrown during construction of a global variable (which is outside scope of any function).
I believe the closest possibility is to use a function-try-block for the body of the constructor of the static.
class MyStatics
{
public:
MyStatics();
private:
X x; // construction may fail
Y y; // construction may fail
// etc
};
static MyStatics all_my_statics;
MyStatics::Mystatics() : x(), y() // implement using a function try block
try
{
if (some_condition) throw some_exception(); // construction may even fail here
}
catch (SomeException &)
{
// handler for SomeException
}
If an exception is thrown during construction of all_my_statics, then any fully-constructed members of it will be destructed (i.e. MyStatics members do not exist within such a catch block).
Within the catch block there aren't many options, after reporting about the caught exceptions. The main options will be;
throw (or rethrow) an exception (since the construction of MyStatics has failed). That exception will cause std::terminate() to be called.
terminate the program in some other way deemed to be "cleaner".
It is not a good idea to swallow an exception thrown during construction of a static since the program (e.g. within main()) will have no indication that statics it relies on have not been properly constructed.
It is more usual to place the static object within a function
X &the_x()
try
{
static X thing;
return thing;
}
catch (Whatever &)
{
// handler
}
Bear in mind that every call of the_x() will attempt to construct thing until one of them succeeds (i.e. if an exception is thrown the first time, the second call will attempt to construct thing, etc). However, if the first call of the_x() within the program can be identified and exceptions from it caught (i.e. wrap it in a try/catch) it is not necessary to catch exceptions from subsequent calls - since, if the first call doesn't throw, the construction of thing has succeeded, and it will not be constructed again.
I found this interesting source. It bases his construction on std::terminate functionality
He proposes to use a sort of global try...catch (you can't continue anymore to run, but you can act depending of exception):
[[noreturn]] void onTerminate() noexcept
{
if( auto exc = std::current_exception() ) {
// we have an exception
try{
rethrow_exception( exc ); // throw to recognize the type
}
catch( MyException const& exc ) {
// additional action
}
catch( MyOtherException const& exc ) {
// additional action
}
catch( std::exception const& exc ) {
// additional action
}
catch( ... ) {
// additional action
}
}
std::_Exit( EXIT_FAILURE );
}
and to register this caller when an exception occurred, earliest possible:
const auto installed{ std::set_terminate(&handler) };
int main() {
// run...
}
But you have to know that you can't be sure that std::set_terminate will be called before any instanciation.
How can I protect myself from using object which isn't fully created when using exceptions?
Should I catch in constructor ? Or maybe it's bad practice ? If I'll catch in constructor object will be created.
#include <stdio.h>
class A
{
public:
A()
{
try {
throw "Something bad happened...";
}
catch(const char* e) {
printf("Handled exception: %s\n", s);
}
// code continues here so our bad/broken object is created then?
}
~A()
{
printf("A:~A()");
}
void Method()
{ // do something
}
};
void main()
{
A object; // constructor will throw... and catch, code continues after catch so basically we've got
// broken object.
//And the question here:
//
//* is it possible to check if this object exists without catching it from main?
// &object still gives me an address of this broken object so it's created but how can I protect myself
// from using this broken object without writing try/catch and using error codes?
object.Method(); // something really bad. (aborting the program)
};
The language itself has no concept of an object being "invalid" in any detectable way.
If the exception indicates that a valid object can't be created, then it shouldn't be handled within the constructor; either rethrow it, or don't catch it in the first place. Then the program will leave the scope of the object being created, and it won't be possible to incorrectly access it.
If that isn't an option for some reason, then you'll need your own way to mark the object as "invalid"; perhaps set a boolean member variable at the end of the constructor to indicate success. This is flaky and error-prone, so don't do it unless you've got a very good reason.
If the object is in an invalid state when a certain exception is thrown, then I would let the exception unwind the call stack so the caller can be notified (and therefore react) to such things.
However, if the exception is one you can recover from, it may be worth trying to do so depend on your application. Make sure you use something like a logger or even simply stderr to indicate this is happening though.
I am going to suggest a first iteration of doing something more like this:
try {
throw "Something bad happened...";
}
catch(const std::exception e) {
cerr << e.what () << endl ; // Better off in the main
throw ;
}
Two things here:
Unless your exception handler handles the exception, it should throw.
Always use exception classes based upon std::exception to that you can always find out what the problem was as shown above.
Consider the following C++ program
struct str
{
int mem;
str()
try
:mem(0)
{
throw 0;
}
catch(...)
{
}
};
int main()
{
str inst;
}
The catch block works, i.e. the control reaches it, and then the program crashes. I can't understand what's wrong with it.
Once the control reaches the end of the catch block of function-try-block of a constructor, the exception is automatically rethrown. As you don't catch it further in main(), terminate() is called.
Here is an interesting reading: http://www.drdobbs.com/184401316
Is it OK to have the following code in my constructor to load an XML document into a member variable - throwing to caller if there are any problems:
MSXML2::IXMLDOMDocumentPtr m_docPtr; //member
Configuration()
{
try
{
HRESULT hr = m_docPtr.CreateInstance(__uuidof(MSXML2::DOMDocument40));
if ( SUCCEEDED(hr))
{
m_docPtr->loadXML(CreateXML());
}
else
{
throw MyException("Could not create instance of Dom");
}
}
catch(...)
{
LogError("Exception when loading xml");
throw;
}
}
Based on Scott Myers RAII implementations in More Effective C++ he cleanups if he alocates any resources i.e. pointers:
BookEntry::BookEntry(const string& name,
const string& address,
const string& imageFileName,
const string& audioClipFileName)
: theName(name), theAddress(address),
theImage(0), theAudioClip(0)
{
try { // this try block is new
if (imageFileName != "") {
theImage = new Image(imageFileName);
}
if (audioClipFileName != "") {
theAudioClip = new AudioClip(audioClipFileName);
}
}
catch (...) { // catch any exception
delete theImage; // perform necessary
delete theAudioClip; // cleanup actions
throw; // propagate the exception
}
}
I believe I am alright in just allowing exceptions to be thrown from CTOR as I am using a smart pointer(IXMLDOMDocumentPtr).
Let me know what you think....
C++ guarantees that in case of an exception all fully constructed objects will be destroyed.
Since m_docPtr is a member of class Configuration it will have been fully constructed before the class Configuration constructor body begins, so if you throw an exception from class Configuration body as you intended in your first snippet m_docPtr will be destroyed.
Do you plan to do anything in the catch block? If nothing, you probably do not need the try catch. On windows, I believe that catch(...) catches hardware interrupts (experts please correct), something to keep in mind.