personal_cloud
personal_cloud

Reputation: 4494

C++: Custom formatting for exceptions uncaught by main()

I am creating a library that contains functions that can throw exceptions. To debug programs that use my library, I would like to provide a custom format-method that will give the programmer more information about these exceptions if they are uncaught by main().

Generally, my library can be called from a main function() written by an end user. The end user does not put a try..catch block in main() because the end user does not expect these exceptions (they should actually be avoided and/or caught by other, buggy libraries, between my library and main(), but they're not, and that's what we need to debug).

// The following example would actually be multiple files,
// but to keep this example simple, put it in "<filename>"
// and compile the following with "g++ <filename>".


// library file

class My_Exception
{
public:
  char const* msg;
  My_Exception(char const* msg) : msg(msg) {}
};

void Library_Function(bool rarely_true = false)
{
  if (rarely_true)
    throw My_Exception("some exceptional thing");
}
// note to discerning user: if you use the "rarely_true" feature,
// be sure to remember to catch "My_Exception"!!!!


// intermediate, buggy, library (written by someone else)

void Meta_Function()
{
  Library_Function(true); // hahahaha not my problem!
}


// main program (written by yet someone else, no "try..except"
// allowed here)

int main()
{
  Meta_Function();
}

When I run the above program, I get:

terminate called after throwing an instance of 'My_Exception'
Abort (core dumped)

I like the way there is an error message telling me about the uncaught exception. I would like to know the best way to add a hook to My_Exception so that the msg string would also be printed in this situation.

I am willing to register callbacks with the runtime system, or add methods to My_Exception, but I don't want to mess with main() itself. (I know this problem could be solved by telling the linker to use a different entry point having a try..catch, and wrapping main() in that, but it will be hard to get the end-user to adopt something like that).

Clearly there is already some exception-checking code after main(), as the above message was printed. The stack trace is:

#0  0x0000155554c0d428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x0000155554c0f02a in __GI_abort () at abort.c:89
#2  0x000015555502e8f7 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x0000155555034a46 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x0000155555034a81 in std::terminate() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x0000155555034cb4 in __cxa_throw ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00000000004006eb in Library_Function() ()
#7  0x00000000004006f4 in main ()
(gdb)

Aside: I don't at all understand why gdb says the program is aborting in Library_Function. That sounds wrong; it should at least have exited from main() after main() failed to catch the exception. Must be some language detail, like it preserves the stack until the exception is handled? In any case, I digress.

Maybe we can extend std::terminate() or cxa__throw() or some other runtime component to print msg in this case?

How this question is different

How come I don't can't print out error from my throw exception? 2 answers -- similar, but 1. my question involves an exception object (not a string) and therefore the point about custom formatting (in the question title) is relevant. 2. missing keyword "uncaught" from the title, so hard to find

Custom error message of re-thrown exception not printed by what() 1 answer -- 1. already contains an answer to my question in their question, so cannot be the same question. Unless you consider "what tool pounds a nail" to be the same question as "why isn't my hammer working". 2. missing keyword "uncaught" from the title

looser throw specifier for ‘virtual const char ro_err::StdErr::what() const’ 1 answer* -- 1. already contains an answer to my question in their question, so cannot be the same question. Unless you consider "what tool pounds a nail" to be the same question as "why isn't my hammer working". 2. missing keyword "uncaught" from the title

Upvotes: 1

Views: 223

Answers (1)

ObliteratedJillo
ObliteratedJillo

Reputation: 5166

As suggested by πάντα ῥεῖ, you can try this

class myexception : public exception
{
public:    
    const char* what() const noexcept override
    {
        char* ch = "some exceptional thing";
        return ch;
    }
};    

void Library_Function(bool rarely_true = false)
{
    if (rarely_true)
        throw myexception();
}

int main()
{
    try 
    {
        Library_Function(true);
    }
    catch (myexception& err)
    {
        std::cout << err.what();
    }
    return 0;
}

Upvotes: 1

Related Questions