为什么我的程序没有从取消引用空指针中捕获异常?



谁能解释一下为什么这个异常没有被捕获?

try {
    // This will cause an exception
    char *p = 0;
    char x = 0;
    *p = x;
}
catch (...) {
    int a = 0;
}

当我运行程序时,它在行*p = x处终止,我希望catch块会导致忽略此异常。

我正在使用Qt Creator(2.2)和Qt 4.7.2在Windows 7 32位的Visual studio 2008上编译。

这里没有抛出c++异常。您正在导致未定义行为,因为*p = x取消了一个指针的空指针值。

异常只在您或您调用的代码执行throw表达式时传播。未定义行为通常不支持catch

结构化异常处理__try和__catch将捕获系统错误,参见:

http://msdn.microsoft.com/en-us/library/swezty51 (v = vs.80) . aspx

解除NULL指针的引用是未定义的行为。通常,这将触发处理器陷阱和操作系统级错误。这可能会被映射到一个信号,比如SIGSEGV,或者一个访问冲突错误,或者它可能会中止你的程序,或者做任何其他事情。

在Windows上,它被映射为一个"结构化异常",这与c++异常是不同的。根据您如何配置MSVC,您可能能够使用catch(...)捕获此问题,但并非总是如此。

如果你想这样做,你需要写一个指针测试:

template<typename T>
inline T* ptr_test(T* test)
{
    if (test == NULL)
    {    throw std::runtime_error("Null Exceception");
    }
    return test;
}

那么你的代码看起来像这样:

try
{
    // This will cause an exception
    char* p = 0;
    char  x = 0;
    *ptr_test(p) = x;  // This is what java does.
                       // Fortunately C++ assumes you are smart enough to use pointers correctly.
                       // Thus I do not need to pay for this test.
                       //
                       // But if you want to pay for the test please feel free.
}
catch (...) 
{
    int a = 0;
}

您需要使用/EHa编译器选项来打开(特定于Microsoft编译器)功能,该功能将启用SEH(结构化异常处理)异常(这是您的空访问触发器)可被catch(...)捕获。

话虽如此,我不建议使用/EHa。最好直接使用__try/__except扩展或SEH API,并将"结构化"异常的处理与c++异常的处理分开。为什么?因为c++异常只是另一种完全合法的定义良好的控制流机制,但大多数触发SEH异常的事情可能表明您的软件已经进入未定义行为的领域,真正明智的做法是优雅地退出。使用/EHa会导致这种重要的区别变得不必要地模糊。

它没有被捕获,因为它不是一个异常-没有抛出任何东西。您正在访问空/未分配内存,这会导致分割错误,这是操作系统本身的信号。

信号只能被信号处理程序捕获,异常对你没有帮助。

异常只有在可能调用throw()的地方才有真正的帮助,比如当您使用提供给它的参数导致除零时,库会抛出异常。

你现在所做的就是解引用一个空指针,这不是一个异常。

如果你想让这段代码捕获一些东西,你必须先抛出一些东西。比如:

try {
    // This will cause an exception
    char *p = 0;
    char x = 0;
    if (p == 0) throw 1;
    *p = x;
}
catch (...) {
    int a = 0;
}

显然,上面示例中的catch块将始终被执行。

最新更新