5

我构建了 llvm/compiler-rt/clang 的 3.1 版本,我正在尝试查看 -fcatch-undefined-behavior 是否真的有任何作用。到目前为止,没有运气。例如我编译并运行

#include <stdio.h>
#include <stdlib.h>

int main() {
    int* x = malloc(sizeof(int) * 10);
    printf("%d\n", x[20]);
    return 0;
}

$ /usr/local/bin/clang -fcatch-undefined-behavior undef_test.c && ./a.out
0

我错过了一些非常简单的东西吗?

4

2 回答 2

4

是:x不是数组。

文档中:

-fcatch-undefined-behavior:打开运行时代码生成以检查未定义的行为。此选项默认为关闭,控制 Clang 是否为未定义的运行时行为添加运行时检查。如果检查失败,__builtin_trap()则用于指示失败。检查是:

  • 下标,其中一个操作数的静态类型是从数组类型衰减的变量,而另一个操作数大于数组的大小或小于零。
  • 移位运算符,其中移位量大于或等于左侧的提升位宽或小于零。
  • 如果控制流达到 __builtin_unreachable。
  • 当 llvm 实现更多 __builtin_object_size 支持时,对 __builtin_object_size 指示我们没有访问有效内存的对象进行读写。尚未检查位域和向量。

我想您想测试下标检查,不幸的是您没有构建一个数组:您构建了一个内存区域(从malloc)然后选择将其解释为一个数组;但从编译器的角度来看,它只是一块内存(请记住mallocis的返回类型void*)。

您可能可以使用以下方法测试此行为:

int main() {
    int x[10] = {};
    printf("%d\n", x[20]);
}

否则,对于特定的内存问题跟踪器,您应该查看 Address Sanitizer 插件。

于 2012-06-28T09:36:08.040 回答
1

-fcatch-undefined-behavior不处理随机指针取消引用。为了处理这种情况,编译器必须将指向数据的大小与指针一起存储,并在每个函数调用中传递该大小。这将与现有的 ABI 不兼容,并且需要重新编译您的程序链接到的所有库。

您可能会争辩说这malloc是一个众所周知的函数,编译器可以假设返回的指针指向请求大小的数组。

但是您会忘记malloc可能会返回NULL。如果编译器假定指针不是NULL,它将优化任何NULL检查(非常危险)。如果编译器假定指针是NULL或指向所请求大小的数组的指针,那么管理起来会有点复杂(我们还没有谈论过freerealloc。此外,任何取消引用malloc-ated 指针而不进行NULL检查的代码都将被视为未定义行为。

更不用说您的程序可能不会链接到标准库,而是链接到提供malloc具有不同语义的自定义实现的库。

于 2012-06-28T09:45:24.600 回答