捕获运行时异常

时间:2010-08-23 04:38:49

标签: c++ exception exception-handling

以下未能捕获异常

int *i;  //intentionally uninitialized

try {
      *i = 6;
    }
catch (const runtime_error e) {
      cout << "caught!" << endl;
    }

它实际上是捕获运行时错误还是异常?

6 个答案:

答案 0 :(得分:4)

*i = 6;行不会抛出runtime_error;它导致未定义的行为。

未初始化的指针将被取消引用,并且您的程序将尝试将值6写入其指向的任何位置(如果它指向任何位置)。这导致未定义的行为。在大多数情况下,这意味着您的程序将立即崩溃或稍后崩溃,因为您将损坏内存中重要的内容。

在标准C ++中,没有办法将这种错误“捕获”为异常;你需要编写你的代码,这样你就不会做这样的事情了。

答案 1 :(得分:3)

声明

除了调试之外,这种事情都没有用。在内存访问异常之后继续执行程序的正当理由并不多,因为通常它表示数据损坏。

那就是说,我认为回答这个问题比通过判断,谴责或审查它更好。


exception派生的C ++类只是方便程序员鼓励良好实践。它们没有特殊的语义,除了名称之外没有任何区别。

更糟糕的是,C ++异常无法传递到信号处理程序之外(在其他语言中会被称为“异常处理程序”,即在非法访问时调用的函数)。该标准有一个特定的警告,

  

可以在符合C程序中用作信号处理程序的[普通旧函数]在用作C ++程序中的信号处理程序时不会产生未定义的行为。在C ++程序中用作信号处理程序的任何其他函数的行为是实现定义的.213)

     

213)特别是,使用异常处理的信号处理程序很可能会出现问题

也就是说,如果你想捕获它,请使用UNIX signal工具来安装一个不使用C ++特性的函数。

#include <csignal>
#include <cstdlib>
#include <cstdio>

void catch_memory( int ) {
    std::printf( "caught!\n" );
    std::abort();
}

int main() {
    std::signal( SIGSEGV, catch_memory );

    int *i = 0;
    *i = 6;
}

答案 2 :(得分:1)

这不是运行时错误,由于编译时错误,它是未定义的运行时行为。

要捕获它(以及许多其他类似的东西),请将编译器设置为可能的最高警告级别。 (作为编译器,与Martin的评论相反,如果你允许的话,检查你是不是很愚蠢。)gcc -Wall在这种情况下会这样做:

$ g++ -Wall test.cpp 
test.cpp: In function ‘int main()’:
test.cpp:<line>: warning: ‘i’ is used uninitialized in this function

就个人而言,我更喜欢这些内容:

$ CXXWARN="-Wall -Wextra -Werror -pedantic -Wno-unused-parameter \
         -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \
         -Wmissing-declarations -Wredundant-decls -Winline"
$ g++ $CXXWARN test.cpp

您的里程可能会有所不同。

答案 3 :(得分:1)

使用C ++ throw关键字抛出适当的异常时,会执行适当的catch子句。这些是C ++例外。

OP代码的结果可能是系统生成的异常(不是C ++异常),严格来说是一种未定义的行为。

答案 4 :(得分:0)

它不会抛出异常。 它可能导致崩溃。 如果您正在项目中工作,那么首先要让您的同行对其进行审核。 代码审查在大多数情况下非常有用。 如果没有,您可以通过使用静态代码分析工具(如Klocwork和动态代码分析工具,如Purify,Bounds Checker等)在开发周期的早期捕获此类错误。

答案 5 :(得分:0)

微软几年前创建了一个名为structured exceptions的东西(a.k.a。,SEH,用于“结构化异常处理”)。尽管C ++异常与结构化异常之间存在一些相似之处,但它们本质上是截然不同的。就个人而言,我已经避开了SEH。

SEH允许您在堆栈溢出或存在内存访问冲突时识别。问题是,在这些情况下你无能为力:你的程序状态在你的处理程序有机会运行之前已经无可挽回地破坏了。虽然你无法修复“无法挽回地破坏”,但你的处理程序可以声称它已经完成(即,即使你的堆栈被粉碎,你也可以继续执行)。

所以你的catch块没有被执行,因为你试图捕获的异常是一个特定于Windows的扩展,它使用完全不同的系统。