C++:main() 未捕获的异常的自定义格式

标签 c++ exception program-entry-point

我正在创建一个库,其中包含可以抛出异常的函数。为了调试使用我的库的程序,我想提供一个自定义格式方法,如果它们未被 main() 捕获,它将为程序员提供有关这些异常的更多信息。

通常,可以从最终用户 编写的main function() 调用我的库。最终用户不会在 main() 中放置一个 try..catch block ,因为最终用户不期望这些异常(它们实际上应该被避免和/或捕获其他有问题的库,在我的库和 main() 之间,但它们不是,这就是我们需要调试的)。

// The following example would actually be multiple files,
// but to keep this example simple, put it in "<filename>"
// and compile the following with "g++ <filename>".


// library file

class My_Exception
{
public:
  char const* msg;
  My_Exception(char const* msg) : msg(msg) {}
};

void Library_Function(bool rarely_true = false)
{
  if (rarely_true)
    throw My_Exception("some exceptional thing");
}
// note to discerning user: if you use the "rarely_true" feature,
// be sure to remember to catch "My_Exception"!!!!


// intermediate, buggy, library (written by someone else)

void Meta_Function()
{
  Library_Function(true); // hahahaha not my problem!
}


// main program (written by yet someone else, no "try..except"
// allowed here)

int main()
{
  Meta_Function();
}

当我运行上面的程序时,我得到:

terminate called after throwing an instance of 'My_Exception'
Abort (core dumped)

我喜欢有一条错误消息告诉我未捕获的异常的方式。我想知道向 My_Exception 添加 Hook 的最佳方法,以便在这种情况下也打印 msg 字符串。

我愿意向运行时系统注册回调,或向My_Exception 添加方法,但我不想弄乱main() 本身。 (我知道可以通过告诉链接器使用具有 try..catch 的不同入口点并在其中包装 main() 来解决这个问题,但它会很难让最终用户采用类似的东西)。

显然在 main() 之后已经有一些异常检查代码,因为上面的消息被打印出来了。堆栈跟踪是:

#0  0x0000155554c0d428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x0000155554c0f02a in __GI_abort () at abort.c:89
#2  0x000015555502e8f7 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x0000155555034a46 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x0000155555034a81 in std::terminate() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x0000155555034cb4 in __cxa_throw ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00000000004006eb in Library_Function() ()
#7  0x00000000004006f4 in main ()
(gdb)

旁白:我完全不明白为什么 gdb 说程序在 Library_Function 中中止。听起来不对;它至少应该在 main() 未能捕获异常后从 main() 退出。一定是一些语言细节,比如它在处理异常之前保留堆栈?无论如何,我离题了。

在这种情况下,也许我们可以扩展 std::terminate()cxa__throw() 或其他一些运行时组件来打印 msg

这个问题有何不同

为什么我不能从抛出的异常中打印出错误? 2 个答案 -- 相似,但 1. 我的问题涉及异常对象(不是字符串),因此关于自定义格式的要点(在问题标题中)是相关的。 2. 标题中缺少关键字“uncaught”,很难找到

what() 未打印的重新抛出异常的自定义错误消息 1 个回答 -- 1. 在他们的问题中已经包含了我的问题的答案,所以不能是同一个问题。除非您认为“用什么工具敲钉子”与“为什么我的锤子不工作”是同一个问题。 2. 标题中缺少关键字“uncaught”

“virtual const char”的宽松抛出说明符 ro_err::StdErr::what() const' 1 个回答* -- 1. 在他们的问题中已经包含了我的问题的答案,所以不能是同一个问题。除非您认为“用什么工具敲钉子”与“为什么我的锤子不工作”是同一个问题。 2. 标题中缺少关键字“uncaught”

最佳答案

根据πìντα ῥεῖ的建议,你可以试试这个

class myexception : public exception
{
public:    
    const char* what() const noexcept override
    {
        char* ch = "some exceptional thing";
        return ch;
    }
};    

void Library_Function(bool rarely_true = false)
{
    if (rarely_true)
        throw myexception();
}

int main()
{
    try 
    {
        Library_Function(true);
    }
    catch (myexception& err)
    {
        std::cout << err.what();
    }
    return 0;
}

关于C++:main() 未捕获的异常的自定义格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52684542/

相关文章:

c++ - 解构具有不完整类型的对象

C++ 将类型名/数据类型名/类名传递给线程构造函数的奇怪案例

Java - 线性搜索时出现 NumberFormatException

azure - 为什么应用程序洞察将 400 错误请求记录为成功请求而不记录异常

c - 为什么 main() 函数不返回浮点值?

c++ - 删除动态链表有困难吗?

c++ - C++换行符中的ascii艺术生成器

java - 一种在数组中的两个索引之间交换位置的方法

unit-testing - 错误 : "Exception has been thrown by the target of an invocation."

JavaFX 最低要求