有没有办法捕获构建静态/全局时抛出的异常?

时间:2012-02-29 17:11:06

标签: c++ exception exception-handling

考虑以下可怕性:

#include <iostream>

struct thing
{
    thing()
    { 
        std::cout << "thing ctor\n";
        throw 5; 
    }
};

void SomeTerminateHandler()
{
    std::cout << "Uncaught exception!?\n";
}

int IHopeThisGetsCalledFirst()
{
    std::cout << "IHopeThisGetsCalledFirst()\n";
    std::set_terminate(SomeTerminateHandler);
    return 2;
}

const int x = IHopeThisGetsCalledFirst();
const thing y;

int main()
{
}

输出:

IHopeThisGetsCalledFirst()
thing ctor
Uncaught exception!?

这依赖于静态初始化顺序(which I can mess with, for MSVS anyway),因此即使以下问题具有可接受的答案,它也不理想。

  • 我可以在SomeTerminateHandler中“捕获”异常,以便显示错误对话框或注明错误的详细信息?
  • abort在上述程序中SomeTerminateHandler之后调用。为什么? This说“默认情况下,终止处理程序调用cstdlib的中止函数。” - 但我没有使用默认的终止处理程序,我的不会调用abort

我可以做些什么来处理静态初始化时的异常。如果没有,为什么不呢?为什么语言中没有允许这样的内容?

3 个答案:

答案 0 :(得分:2)

  

我可以在SomeTerminateHandler中“捕获”异常,以便显示错误对话框或注明错误的详细信息?

没有 - 只有异常处理程序才能访问抛出的异常。

  在上述程序中abort之后调用

SomeTerminateHandler。为什么呢?

您的终止处理程序不得返回;标准(C ++ 11,18.8.3.1)要求它“终止程序的执行而不返回调用者” - 你链接到的页面也说同样的事情。如果你打破了这个要求,那么任何事情都可能发生。

  

我有什么办法可以处理静态初始化时的异常吗?

您可以在构造函数中捕获异常;或者你可以避免复杂的静态物体。

  

如果没有,为什么不呢?为什么语言中没有允许这样的内容?

我无法回答原因,但C ++并不能很好地处理复杂的静态对象。即使您的编译器确实有非标准扩展来指定初始化顺序,我建议尽可能避免使用它们。

答案 1 :(得分:1)

  

我可以做些什么来处理静态异常   初始化时间。如果没有,为什么不呢?为什么没有东西在里面   语言允许这个?

对于在文件范围外部链接或创建的用户定义对象,C ++没有任何明确定义的构造。对于未定义的初始化顺序等问题,通常会出现问题。如果没有明确定义初始化顺序等内容应该发生什么,那么定义有意义的try / catch行为就会很困难(如果有人将try / catch块放在哪里,例如,如果在任何编译单元中构造任何对象,系统可以扔?)。

对于一个更哲学的答案,我冒昧地猜测C ++旨在解决的一个问题是需要大量的全局对象。该语言并不打算为它们提供明确定义的行为,因为它们通常应该首先被避免。

如果你想快速修复,我们可以以懒惰的方式构建东西:

thing& my_thing()
{
    static thing obj;
    return obj;
}

这确保在第一次调用此函数之前不会构造thing,这意味着它不会在主入口点之外构造,除非你有另一个全局对象调用它(直接或间接)通过它的构造函数。

最终如果你以这种方式一起避免用户定义类型的全局实例会更好,但如果你无法抗拒诱惑,我建议至少应用一种懒惰的初始化形式。

答案 2 :(得分:0)

  

我可以做些什么来处理静态初始化时的异常。如果没有,为什么不呢?

不,因为标准没有指定初始化顺序。

唯一不做的事情,或者至少最小化在main之前初始化的对象数量。将它们放在一个地方也是非常好的。

  

在上述程序中的SomeTerminateHandler之后调用abort。为什么?这说“终止处理程序默认调用cstdlib的中止函数。” - 但我没有使用默认的终止处理程序,我的也没有调用abort。

您的处理程序很可能未按时初始化(在初始化处理程序之前抛出异常)。