【问题标题】:cpp exception get the details of throw callercpp 异常获取 throw 调用者的详细信息
【发布时间】:2018-11-04 17:53:15
【问题描述】:

我有一些自定义异常,如下所示

class myexception: public exception
{
  virtual const char* what() const throw()
  {
    return "My exception happened";
  }
} myex;

void testException(){
 throw myex;
}

void doSomething2(){
   testException();
}
void doSomething1(){
   doSomething2();
}


int main () {
  try
  {
    doSomething1();
  }
  catch (exception& e)
  {
    cout << e.what() << '\n';
  }
  return 0;
}

所以在主函数中我无法知道 throw 的调用者(哪个函数抛出了异常),如何获取该详细信息?

【问题讨论】:

  • 为什么不为异常写一个有意义的消息,其中包括抛出函数的名称?在 C++11 中,您可以使用 __func__ 获取当前函数的名称。
  • 出于调试目的,您可以设置断点并查看调用堆栈。如果你也想在发布中,也许像这里cplusplus.com/reference/exception/rethrow_exception 一样重新抛出异常。根据您的编译器,您还可以使用 _FUNCTION_ 或 _FILE_ 和 _LINE_ 来抛出 return
  • 在 C++11 及更高版本中,有一个预定义的宏 __func__ 可用于获取函数的名称,在该函数中它被称为以 nul 结尾的字符串(但不是字符串文字),并且可以传递给异常的构造函数并存储一个副本。对于 C++11 之前的编译器的任何答案(如果有的话)都将是特定于编译器的,因此您需要指定您的编译器。

标签: c++ exception


【解决方案1】:

这应该会有所帮助:

How to automatically generate a stacktrace when my gcc C++ program crashes

您可以找到打印调用堆栈并在异常处理程序中打印的方法。

【讨论】:

  • 嗨,当我运行这个函数名中给出的例子时,没有打印出来,下面是我的输出,/test/Example/Debug/backstrace[0x400749] /lib/x86_64-linux-gnu/libc .so.6(+0x36cb0)[0x7f1388167cb0] /test/Example/Debug/backstrace[0x4007a2] /test/Example/Debug/backstrace[0x4007ca] /test/Example/Debug/backstrace[0x4007d5] /test/Example/Debug /backstrace[0x400804] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x7f1388152f45] /test/Example/Debug/backstrace[0x400669]
  • 这个链接panthema.net/2008/0901-stacktrace-demangled也可以,但是调用者函数名没有打印出来
【解决方案2】:

据我所知,在C++ 中没有简单的便携 方法可以做到这一点。有一些相当复杂的方法可以使用特定于操作系统的调用来获取完整的堆栈跟踪。

我用来获取异常源的最简单方法是使用 MACROS。

不建议在可以避免的地方使用宏,但这是证明有用的少数地方之一。

我倾向于使用比这稍微复杂一些的东西,但这是它的基础:

#ifndef NDBUG
#define throw_runtime_error(msg) \
    throw std::runtime_error(std::string(msg) \
        + " line: " + std::to_string(__LINE__) \
        + " file: " + std::string(__FILE__))
#else
#define throw_runtime_error(msg) throw std::runtime_error(msg)
#endif

void doSomething2(){
    throw_runtime_error("My runtime error.");
}
void doSomething1(){
   doSomething2();
}

int main()
{
    try
    {
        doSomething1();
    }
    catch(std::exception const& e)
    {
        std::cerr << e.what() << '\n';
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

您不会获得完整的跟踪信息,但可以看到异常是在哪里引发的。 MACRO 仅在未设置 NDBUG 时包含调试信息,因为 release 构建应设置该宏以禁用调试信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    相关资源
    最近更新 更多