代码之家  ›  专栏  ›  技术社区  ›  MMMMMCK

C++获取std::out\u of\u range异常的位置

  •  0
  • MMMMMCK  · 技术社区  · 8 年前

    我正在编写一个相当长的程序,在运行了一段时间后,突然我发现:

    terminate called after throwing an instance of 'std::out_of_range'
     what(): basic_string::substr
    

    作为异常处理的新手,我做了一些研究,发现通过在我的主要功能中添加以下内容,我可能会获得更多信息:

    int main(int argc, char **argv){
        try{
            //stuff
        }
        catch(exception const &exc){
            cerr << "Caught exception: " << exc.what() << endl;
        }
    }
    

    其结果是以下输出:

    Caught exception: basic_string::substr
    

    这并不比默认输出更有用;它没有告诉我任何关于触发核心转储的行(我的程序中有许多substr调用)、substr试图处理的数据等的信息。是否有一种方法可以在C++中显示这样的信息,或者是我使用gdb之类的调试器的唯一选择?

    1 回复  |  直到 8 年前
        1
  •  1
  •   Richard Hodges    8 年前

    有几种方法。

    1. 正如您所说,调试器——但一旦代码投入生产,它就帮不了您。

    2. 嵌套异常和函数try块。e、 g.:

    #include <exception>
    #include <stdexcept>
    #include <iostream>
    #include <sstream>
    #include <iomanip>
    
    void bar(std::string& s, int i)
    try
    {
        s.at(i) = 'A';
    }
    catch(...)
    {
        std::ostringstream ss;
        ss << "error in bar(" << std::quoted(s) << ", " << i << ")";
        std::throw_with_nested(std::runtime_error(ss.str()));
    }
    
    void foo(std::string& s)
    try
    {
        bar(s, 6);
    }
    catch(...)
    {
        std::ostringstream ss;
        ss << "error in foo(" << std::quoted(s) << ")";
        std::throw_with_nested(std::runtime_error(ss.str()));
    }
    
    void stuff()
    try
    {
        std::string s;
        foo(s);
    }
    catch(...)
    {
        std::throw_with_nested(std::runtime_error("error in stuff()"));
    }
    
    void print_exception(std::ostream& os, const std::exception& e, int level =  0)
    {
        os << std::string(level, ' ') << "exception: " << e.what() << '\n';
        try {
            std::rethrow_if_nested(e);
        } catch(const std::exception& e) {
            print_exception(os, e, level+1);
        } catch(...) {}
    }
    
    int main()
    {
        try{
            stuff();
        }
        catch(std::exception& e)
        {
            print_exception(std::cerr, e);
            return 127;
        }
        return 0;
    }
    

    示例输出:

    exception: error in stuff()
     exception: error in foo("")
      exception: error in bar("", 6)
       exception: basic_string::at: __n (which is 6) >= this->size() (which is 0)
    
    1. 你可以使用 boost::stacktrace 代替上述嵌套的异常处理。

    http://coliru.stacked-crooked.com/a/f21bd35632a0a036