繁体   English   中英

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

[英]How to catch run time error in C and C++?

就像修改CONST int一样,

我可以注册一个特定的 function 来处理运行时错误,这样这种操作就会失败而不是终止应用程序吗?

如果您的意思是 C++,则有一个名为runtime_error的异常 class 。 您可以使用 catch 子句捕获它:

catch(std::runtime_error& e) {}

但是,C 和 C++ 中的许多事情(例如修改 const int)会导致未定义的行为 您无法在运行时捕获它们。 您无法捕获它们,因为没有抛出异常(从技术上讲,任何事情都可能发生,包括抛出异常(仅限 C++),但这不是您可以或不应该希望的)。

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

根据规范,修改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,但修改 function 工作正常。 这是由于 function 指针的特殊性质,其值并不总是在运行时确定,因此该值必须存储在可写的 memory 中。

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

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

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

在与 POSIX 兼容的操作系统中,您的程序可以在 memory 访问受限的情况下捕获SIGSEGV信号,在无效指令的情况下捕获SIGILL信号,在非法浮点运算(例如被零除)的情况下捕获SIGFPE

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

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

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

我大错特错。

尝试修改 const 限定的变量确实是未定义的行为,而且似乎已经有好几年了。 它可能会也可能不会产生运行时错误; 能不能用得看平台。

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

我非常抱歉以其他方式提出索赔; 以及侮辱这个群体的成员。 尤其是迪特里希。

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

您必须知道这一点,并且一定是您的示例考虑不当,但是无论如何都值得注意,以防有人误解:

在 C 中,在运行时没有const int (或const其他任何东西)这样的东西; const纯粹是一个编译时概念。 因此,修改const int没有运行时错误。

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

这些情况会导致不可预知的结果,正如您所指出的,这些结果有时可能包括程序继续运行并看起来“工作”,或者它可能会崩溃,或者鼻恶魔可能会自发地出现。

如果您想捕捉未定义行为的使用,那么您可以在某些情况下使用工具来执行此操作。

例如, Electric Fence非常擅长揭示您不应该写入 memory 的位置(尽管不要在发布版本中激活它。)。 这是否适用于写入您抛弃的const的东西将取决于应用了哪些优化; object可能具有可写的 memory,并且在物理上无法确定您实际上做错了什么。

你不会得到一个整洁的语言层异常。 由于无论如何您都将不得不在工具路线上使用 go,因此只需尽可能应用 static 和动态分析工具并配置文件 没有万无一失的方法可以突然打开“理智地通知我所有未定义行为的使用”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM