Say I have:
try
{
externalLibrary::doSomething();
}
catch (std::exception &e)
{
//yay I know what to do
}
catch (...)
{
//darn, I've no idea what happened!
}
There might be cases you get an exception and you don't know where it's coming from or why - in some external library with no debug info. Is there a way to find what was thrown, or otherwise obtain any data associated with it? They might be doing:
throw myStupidCustomString("here is some really useful information");
But I'd never know if I catch ...
Working in MSVC++ 2008 if it matters.
The try-catch is the simplest method of handling exceptions. Put the code you want to run in the try block, and any Java exceptions that the code throws are caught by one or more catch blocks. This method will catch any type of Java exceptions that get thrown. This is the simplest mechanism for handling exceptions.
If a catch block cannot handle the particular exception it has caught, you can rethrow the exception. The rethrow expression ( throw without assignment_expression) causes the originally thrown object to be rethrown.
There are two types of exceptions: a)Synchronous, b)Asynchronous (i.e., exceptions which are beyond the program's control, such as disc failure, keyboard interrupts etc.). C++ provides the following specialized keywords for this purpose: try: Represents a block of code that can throw an exception.
Any code that may throw an exception is placed inside the try block. If an exception is thrown, the catch block is entered, and the program can do the appropriate operation to recover or to alert the user. The code in the finally block is always executed and can do clean up after an exception occurs.
If you use gcc or CLANG you can use a trick to know the 'unknown' exception type. Keep in mind that this is NON-standard !
#include <cstdlib>
#include <iostream>
#include <cxxabi.h>
using namespace __cxxabiv1;
std::string util_demangle(std::string to_demangle)
{
int status = 0;
char * buff = __cxxabiv1::__cxa_demangle(to_demangle.c_str(), NULL, NULL, &status);
std::string demangled = buff;
std::free(buff);
return demangled;
}
struct MyCustomClass
{};
int main(int argc, char * argv[])
{
try
{
throw MyCustomClass();
}
catch(...)
{
std::cout << "\nUnknown exception type: '" << util_demangle(__cxa_current_exception_type()->name()) << "'" << std::endl;
}
return(0);
}
Because C++ is statically typed, you must catch a known type. However, you can call an external function (or set of functions) which handle exception types unknown at the point you call them. If these handlers all have known types, you can register them to be dynamically tried.
struct myStupidCustomString {
myStupidCustomString(char const *what) : what (what) {}
char const *what;
};
void throws() {
throw myStupidCustomString("here is some really useful information");
}
// The external library can provide a function, or you can provide a wrapper, which
// extracts information from "unknown" exception types.
std::string extract_from_unknown_external_exception() {
try { throw; }
catch (myStupidCustomString &e) {
return e.what;
}
catch (...) {
throw; // Rethrow original exception.
}
}
Use:
void example() {
try { throws(); }
catch (...) {
try {
std::string extracted = extract_from_unknown_external_exception();
std::cout << "extracted: " << extracted << '\n';
}
catch (...) {
// Chain handlers for other types; e.g. exception types from other libraries.
// Or do something generic for the unknown exception.
// Or rethrow the original unknown exception:
throw;
}
}
}
Handler chain:
typedef std::string Extract();
std::vector<Extract*> chain (1, &extract_from_unknown_external_exception);
// Chain would normally be initialized using whatever scheme you prefer for
// initializing global objects.
// A list or other container (including a manual linked list that doesn't
// require dynamic allocation) may be more appropriate, depending on how you
// want to register and unregister handlers.
std::string process_chain() {
for (std::vector<Extract*>::iterator x = chain.begin(); x != chain.end(); ++x) {
try {
return (*x)();
}
catch (...) {} // That handler couldn't handle it. Proceed to next.
}
throw; // None could handle it, rethrow original exception.
}
void example() {
try { throws(); }
catch (...) {
try {
std::string extracted = process_chain();
std::cout << "extracted: " << extracted << '\n';
}
catch (...) {
throw; // Rethrow unknown exception, or otherwise handle it.
}
}
}
Finally, if you know implementation specifics, you can use those to extract whatever additional information your implementation exposes. C++0x exposes some specifics in a portable way, too; look at std::exception_ptr.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With