66007

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

Question:

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 <em>end user</em>. 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?

<strong>How this question is different</strong>

<em>How come I don't can't print out error from my throw exception? 2 answers</em> -- 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

<em>Custom error message of re-thrown exception not printed by what() 1 answer</em> -- 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

<em>looser throw specifier for ‘virtual const char</em> 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

Answer1:

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; }

Recommend

  • Why a class has only one destructor? [duplicate]
  • Cannot terminate threads
  • How does `std::terminate` know to treat `std::exception`s specially?
  • Handling exceptions in a class library enveloping a device driver
  • Why does .addView throw this parent/child exception?
  • Read a file in “chunks” using PHP
  • API (curl)Command to Approve a promoted build Job in Jenkins
  • Leaflet z-index
  • auth.provider is not set to 'password' when user signs-in with email and password
  • How can I extend PHP DOMElement?
  • Memory error in python- how to use more memory
  • Differences in dis-assembled C code of GCC and Borland?
  • Admob requires api-13 or later can I not deploy on old API-8 phones?
  • Test if a set exists before trying to drop it
  • Spark fat jar to run multiple versions on YARN
  • Asynchronous UI Testing in Xcode With Swift
  • Algorithm for a smudge tool?
  • Highlight one bar in a series in highcharts?
  • Scrapy recursive link crawler
  • Spring Data JPA custom method causing PropertyReferenceException
  • NetLogo BehaviorSpace - Measure runs using reporters
  • Join two tables and save into third-sql
  • Perl system calls when running as another user using sudo
  • How to model a transition system with SPIN
  • ORA-29908: missing primary invocation for ancillary operator
  • Calling of Constructors in a Java
  • SVN: Merging two branches together
  • Hibernate gives error error as “Access to DialectResolutionInfo cannot be null when 'hibernate.
  • PHP: When would you need the self:: keyword?
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • sending mail using smtp is too slow
  • Checking variable from a different class in C#
  • Busy indicator not showing up in wpf window [duplicate]
  • Sorting a 2D array using the second column C++
  • Why is Django giving me: 'first_name' is an invalid keyword argument for this function?
  • How can I use `wmic` in a Windows PE script?
  • Converting MP3 duration time
  • java string with new operator and a literal