[英]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.