Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to debug a std::bad_cast exception

Tags:

c++

debugging

class GAGenome {
  virtual void method(){};
};

template <class T>
class GAArray {
};

template <class T>
class GA1DArrayGenome : public GAArray<T>, public GAGenome {
};

int main() {
  GA1DArrayGenome<float> genome;
  const GAGenome & reference = genome;
  auto cast = dynamic_cast<const GA1DArrayGenome<int> &>(reference);
}

This obviously wrong program (since template parameter is different) crashes with

terminate called after throwing an instance of 'std::bad_cast'
  what():  std::bad_cast
Aborted (core dumped)

Is there a way how to get precise diagnostics of what went wrong, beyond the runtime error message? Something, that can point out the int/float mistake to me? I am looking for a descriptive error message like

const GA1DArrayGenome<float> & cannot be cast to const GA1DArrayGenome<int> &

Even better, since C++ types can get hairy at times, the tool could notice the precise discrepancy in the template parameter.

like image 714
user7610 Avatar asked Apr 30 '14 15:04

user7610


2 Answers

You can also abandon direct uses of dynamic_cast and wrap it in your own template machinery:

#include <sstream>

class my_bad_cast: public std::bad_cast {
public:
    my_bad_cast(char const* s, char const* d): _source(s), _destination(d) {
#ifdef WITH_BETTER_WHAT
        try {
            std::ostringstream oss;
            oss << "Could not cast '" << _source
                << "' into '" << _destination << "'";
            _what = oss.str();
        } catch (...) {
            _what.clear();
        }
#endif
    }

    char const* source() const { return _source; }
    char const* destination() const { return _destination; }

#ifdef WITH_BETTER_WHAT
    virtual char const* what() const noexcept {
        return not _what.empty() ? _what.c_str() : std::bad_cast::what();
    }
#endif

private:
    char const* _source;
    char const* _destination;
#ifdef WITH_BETTER_WHAT
    std::string _what;
#endif
    // you can even add a stack trace
};

template <typename D, typename S>
D my_dynamic_cast(S&& s) {
    try {
        return dynamic_cast<D>(std::forward<S>(s));
    } catch(std::bad_cast const&) {
        throw my_bad_cast(typeid(S).name(), typeid(D).name());
    }
}
like image 53
Matthieu M. Avatar answered Nov 06 '22 21:11

Matthieu M.


You can load your program (compiled with debug information, e.g. -g in gcc and glang) in gbd, tell gdb to catch exceptions with catch throw and then look at the call stack to see exactly where the exception was thrown.

std::bad_cast is thrown when a dynamic_cast fails at runtime.

like image 23
Baum mit Augen Avatar answered Nov 06 '22 22:11

Baum mit Augen