如何捕获C和C ++中的运行时错误?

时间:2011-06-29 14:07:32

标签: c++ c runtime-error

喜欢修改CONST int

我是否可以注册一个特定的函数来处理运行时错误,以便这种操作失败而不是终止应用程序?

7 个答案:

答案 0 :(得分:6)

如果您的意思是C ++,那么有一个名为runtime_error的异常类,您可以使用catch子句来捕获它

catch(std::runtime_error& e) {}

但是,C和C ++中的许多内容(如修改const int)会导致undefined behvior。你无法捕捉它们的运行时间。你无法捕捉它们。因为没有抛出任何异常(从技术上讲,任何事情都可能发生,包括抛出异常(仅限C ++),但这不是你能够或应该希望的东西)

解决方案是编写干净的安全代码。为此,许多书中列出了许多建议:)

答案 1 :(得分:2)

根据规范,修改const是“未定义的行为”,因此编译器可以执行任何操作。在实践中,许多实现有时会为此类代码生成运行时错误,但很多实现不会。它通常取决于程序的性质。这是一个例子:

#include <stdio.h>
#include <string.h>

typedef int (*fn)(const char *);

extern const fn global_fn_ptr;
extern const char global_string[];
const fn global_fn_ptr = puts;
const char global_string[] = "hello";

int main(int argc, char *argv[])
{
    puts("Setting global_fn_ptr to NULL");
    *(fn *)&global_fn_ptr = NULL;
    puts("Setting string to \"bye\"");
    strcpy((char *)global_string, "bye");
    return 0;
}

在我的系统上,我通过修改字符串得到一个SIGBUS,但是修改函数工作正常。这是由于函数指针的特殊性质,其值并不总是在运行时确定,因此该值必须存储在可写内存中。

在C ++中捕获SIGBUS或SIGSEGV并将其转换为异常通常是不安全的。从信号处理程序中正确地longjmp也是非常困难的 - 在C中使用这种模式的代码的一半可能是不正确的。最安全的选择是让程序立即终止,或者如果你真的需要运行时的这种帮助,那么就要非常小心地使用C代码,这样你就可以在非本地退出中释放适当的资源--C ++不会这样做,因为{{ 1}}不会调用析构函数。

或者您可以转移到C#或Java,这两者都有为您执行此操作的运行时以及之后进行清理的垃圾收集器。

答案 2 :(得分:1)

这是特定于操作系统的。语言本身将这些指定为未定义的行为。

在符合POSIX标准的操作系统中,如果内存访问受限,您的程序可以捕获SIGSEGV信号,如果指令无效则可以捕获SIGILL,如果是非法,则SIGFPE浮点运算,例如除以零。

答案 3 :(得分:1)

在C运行时中,错误通常会生成可由信号处理程序处理的信号。

在C ++中,运行时错误也可以作为可以在try / catch块中捕获的异常抛出。

要在某个时刻继续而不是崩溃,你需要在信号处理程序中使用setjmp / longjmp - 从程序错误中捕获信号后返回是不安全的

答案 4 :(得分:1)

我错了。

尝试修改const限定的变量确实是未定义的行为,并且看起来已经存在了几年。它可能会也可能不会产生运行时错误;是否取决于平台。

n1570,这是C标准下一次迭代的委员会草案,在第6.7.3节给出了规则,正如@Dietrich Epp耐心地指出的那样。自C89以来,该部分的措辞可能没有改变。

我非常抱歉否则声称;对于这个组织的侮辱成员。特别是迪特里希。

现在,我在哪里可以找到一些美味的自由放养的乌鸦?

答案 5 :(得分:0)

你必须知道这一点,并且必须考虑到你的榜样,但是如果有人得到错误的想法,那么值得注意:

在C中,在 运行时 时,没有const int(或const任何其他内容); const纯粹是 编译时 概念。因此,修改const int没有运行时错误。

答案 6 :(得分:0)

如果我理解正确,那么您所谈论的场景是根据语言(通常)未定义的场景。

这些情况导致不可预测的结果,正如您所指出的,这些结果有时可能包括程序继续并显示为“工作”,或者它可能会崩溃,或者鼻子恶魔可以自发地存在。

如果你想捕获未定义行为的使用,那么你可以使用工具在某些情况下

例如,Electric Fence很好地揭示了你不应该写入内存的位置(尽管不要在发布版本中激活它!)。这是否适用于写入你所用的const内容的东西将取决于已应用的优化;对象可能会具有可写内存,并且在物理上不可能确定您实际上是在做错事。

你不会得到的是一个整洁的语言层异常。由于您无论如何都必须沿着工具路线前进,所以尽可能使用静态和动态分析工具以及 profile 。没有万无一失的方法突然开启“通知我使用未定义的行为”。