1

I have a library I use that throws something, but I don't know how to identify what was being thrown.

Sample code to reproduce this:

int main()
{
    char* memoryOutOfBounds;
    unsigned __int64 bigNumber = -1;
    try {
        throw std::string("Test");
        memoryOutOfBounds = new char[bigNumber];
    }
    catch (const std::bad_alloc& ex)
    {
        printf("Exception: %s\n", ex.what());
    }
    catch (...)
    {
        printf("Unknown.\n");
    }

    return 0;
}

The new char[bigNumber] will throw a std::bad_alloc, which is derived from std::exception and will enter the first branch. The other one, throw std::string will enter the second branch. How can I check the object that was thrown? I tried with a catch(void*) in the hopes to catch any object in memory, but that did not happen, so how can I find out what was thrown and from there debug what may have caused this?

SinisterMJ
  • 3,425
  • 2
  • 33
  • 53
  • 2
    Refer to the docs of the library? Check the source code of the library? You can't know it from within C++ alone in an abstract way. You may try [RTTI](https://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI), but it's not that simple. – The Quantum Physicist Nov 30 '17 at 11:19
  • So no possibility to find out the type of object? I mean, its from some library, so a namespace already would help. – SinisterMJ Nov 30 '17 at 11:21
  • Not in a programmatic C++ way. I.e., not at run time. Just occurred to me, you can try a debugger. Debuggers can probably do this. – The Quantum Physicist Nov 30 '17 at 11:22
  • `catch (const std::string& s)` – rustyx Nov 30 '17 at 11:52
  • 1
    It's likely that the library will have a base class for all exceptions that they raise. You just need to read the docs and find out what that is so you can catch it. – UKMonkey Nov 30 '17 at 11:57
  • But is there any way to do something like catch(&genericObject), so that I can get at least a pointer to the object thrown? – SinisterMJ Nov 30 '17 at 12:07
  • no, because C++ doesn't _have_ any generic object that serves as a base class for everything else. The norm is for exceptions to derive from `std::exception` as suggested, so you have a common base class to catch. – Useless Nov 30 '17 at 12:15
  • 1
    ... you can _almost_ get there with `std::exception_ptr current_exception()`, but it seems like all you can usefully do with that is re-throw it, which means you still need a stack of `catch` blocks to find out what was in there – Useless Nov 30 '17 at 12:18
  • What would you do with such a pointer? – n. m. could be an AI Nov 30 '17 at 12:20
  • This question, as asked, has no solution in standard C++. The `catch (...)` block receives no information about the caught exception and the only thing it can do is rethrow (i.e. a `throw;` statement or, if `std::current_exception()` is employed, `std::rethrow()`). However, to get information about the ACTUAL thrown exception, it is necessary to have a `catch()` that specifies a matching type. – Peter Nov 30 '17 at 12:24

3 Answers3

2
catch (...) {}

means: Catch absolute everything that was thrown and drop it. This is only meant as a safeguard, so no exceptions fly out of the window and bring down the whole house. (Aka: Application Termination by Unhandled Exception")

There is no way to tell what was thrown in here.

But as you actually know that an std::string can be thrown, you can catch it in a

catch (const std::string& s) {}

block. You do need to know what (type) was thrown whenever you want to catch exceptions.

However, most libraries which add their own types for exceptions will have them inherit from std::exception. Therefore a

catch (const std::exception& e) {
    std::cerr << e.what() << std::endl;
}

block should get them.

If they do not inherit from std::exception and/or block the what() method, it is a stupid way to make the usage of their library extra difficult.

However, somewhere in the documentation of the library the exception throwing behaviour should be explained.

Edit : I think that Point 1. under "How should I design my exception classes" on the Boost Error Handling document is something every library developer should keep in mind. And hopefully the developers of your library did keep that principle in mind. ;-)

Yamakuzure
  • 367
  • 2
  • 9
  • My question is, I do not know what is being thrown. In an ideal case, I would find out what type of class is being thrown, in a less ideal case I would want to know the pointer to the thing being thrown. – SinisterMJ Nov 30 '17 at 12:08
  • @SinisterMJ : Sorry, hit the wrong button. I have edited my answer to include the rest. Hopefully this'll help. – Yamakuzure Nov 30 '17 at 12:13
  • @SinisterMJ: sorry, but C++ simply doesn't provide what you are looking for. You have to know what is being thrown so you can catch it by type. `catch(...)` loses all type information. If the library author does not document what is being thrown, complain to the author. – Remy Lebeau Nov 30 '17 at 19:07
1

There really is no standard C++ way to query any information about the exception that is being thrown. Which is unfortunate, because the runtime has that information in order to match catch blocks. But there is just no access to that information in user code.

If it's purely for research purposes, like just finding out what the type is because the library you're using lacks documentation, you could use std::current_exception() to get a std::exception_ptr object that stores (or references) the thrown exception internally. This type is implementation-defined, but your debugger might happen to provide you with enough information.

#include <exception>

void foo()
{
    try
    {
        function_that_throws();
    }
    catch(...)
    {
        std::exception_ptr p = std::current_exception();
        // break here and inspect 'p' with a debugger
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
oisyn
  • 1,306
  • 5
  • 14
-1

This stackoverflow post would be helpful- C++ get description of an exception caught in catch(...) block

Since C++11 you can capture the current exception with a pointer:

std::exception_ptr p;     // default initialization is to nullptr

try {
      throw std::string("Test");
}
catch(...)
{
     p = std::current_exception();
}
Amit Rastogi
  • 926
  • 2
  • 12
  • 22
  • The C++11 code you showed doesn't answer the question that was asked. You can't get any type information from the `std::exception_ptr` itself. You can only pass it around and re-throw it. As shown in the other answer you linked to, you would have to re-throw and catch the exception to discover its type, and even that is a guessing game at best. – Remy Lebeau Nov 30 '17 at 19:00