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

时间:2011-08-31 21:33:49

标签: c++ exception-handling

有些人可以解释一下为什么没有发现这个例外。

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 Studios 2008进行编译。

7 个答案:

答案 0 :(得分:10)

这里没有抛出C ++异常。您正在导致未定义的行为,因为*p = x使用空指针值解析指针。

只有当您或您调用的代码执行throw表达式时,才会传播异常。 未定义的行为通常不会catch能够使用。

答案 1 :(得分:3)

取消引用NULL指针是未定义的行为。通常,这将触发处理器陷阱和OS级错误。然后,这可能会映射到一个信号,例如SIGSEGV,或者一个访问冲突错误,或者它可能会中止您的程序,或者执行其他任何操作。

在Windows上,它被映射到“结构化异常”,这是与C ++异常不同的野兽。根据您配置MSVC的方式,您可以使用catch(...)来捕获此信息,但并非总是如此。

答案 2 :(得分:3)

如果您需要,您需要编写指针测试:

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;
}

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

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

信号只能由信号处理程序捕获,例外情况不会对您有所帮助。

异常仅在某些内容可能会调用throw()的区域中提供帮助,就像当您使用您提供的参数导致零除零时抛出异常的库。

答案 5 :(得分:1)

你现在正在做的就是取消引用一个空指针,这不是一个例外。

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

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

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

答案 6 :(得分:1)

您需要使用/EHa编译器选项来启用(Microsoft编译器specific)功能,该功能将启用SEH(Structured Exception Handling)异常(这是您的空访问触发的)可以通过catch(...)进行追踪。

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