我刚刚在UB(Undefined Behavior)上看了一场有趣的演讲,我try 了一些东西.

请考虑以下代码:

#include <limits.h>
#include <stdio.h>

int f(int x) {
    return x + 10;
}

int main(void) {
    int i;
    i = INT_MAX - 3;

    printf("i = %d\n",i);
    printf("f(%d) = %d\n",i,f(i));

    printf("Hello World\n");

    return 0;
}

使用以下工具进行编译时:

clang -O0 -fsanitize=undefined a.c

然后运行程序,就会出现运行时错误,clang会详细解释是什么地方出了问题:

runtime error: signed integer overflow: 2147483644 + 10 cannot be represented in type 'int'

然而,程序将继续超过offending行并执行Hello World消息,and退出状态/返回代码将为0,就好像没有发生任何坏事一样.

当使用clang时,如何在C程序中强制hard crash / exception(类似于assert()错误)?

感谢您提前给我任何有用的答复.

PS:我了解到错误消息不能在编译时产生,只能在运行时产生,但我没有想到在启用-fsanitize=undefined时会产生如此loose的后果.

期望:

clang -O0 -fsanitize=undefined a.c -o a.out
./a.out
echo $?
  • 未显示Hello World
  • 退出状态为!= 0

推荐答案

https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

对于大多数判断(判断),插入指令的程序会打印详细的 错误报告,并在判断失败时继续执行.您可以使用 以下选项用于更改错误报告行为:

  • -fno-sanitize-recover=...:打印详细错误报告并退出程序;

  • -fsanitize-trap=...:执行trap 指令(不需要UBSAN运行时支持).如果没有捕捉到信号,程序将 通常由于SIGILL或SIGTRAP信号而终止.

听起来你想用-fsanitize=undefined -fno-sanitize-recover=all.

C++相关问答推荐

在使用GTK 4 Columnview列表模型时,如何为多列添加排序函数.C编码,Linux/GNOME环境

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

以前版本的tty_ldisc_ops.ioctl()是否也需要文件参数?

在一个小型玩具项目中实现终端历史记录功能

C lang:当我try 将3个或更多元素写入数组时,出现总线错误

如何捕捉只有换行符或空格字符缓冲区的边缘大小写

在Rust和C之间使用ffi时如何通过 struct 中的[U8;1]成员传递指针

SSH会话出现意外状态

为什么函数是按照定义的顺序执行的,而不是按照从avr-c中的int main()调用的顺序执行的?

为什么电路板被循环删除?

递归打印二维数组(C编程)

条件跳转或移动取决于未初始化值(S)/未初始化值由堆分配创建(Realloc)

区分MySQL C界面中的文本和BLOB字段

Tcl_GetDoubleFromObj在列表的迭代中是一个缺点

为什么这个代码的最后一次迭代不能正常工作?

如何在Rust中处理C的longjmp情况?

使用替代日历打印日期

仅使用其内存地址取消引用 C 中的 struct

如何确保 gcc + libc 对于多字节字符串使用 UTF-8,对于 wchar_t 使用 UTF-32?

strlen 可以是[[未排序]]吗?