Mic*_*ris 5 c gcc pointers clang undefined-behavior
如果一个数组超出了另一个数组的末尾,则此代码将通过指针写入一个值。
#include <stdio.h>
#include <inttypes.h>
extern int first[], second[];
#define ADDR_AFTER(ptr) ((uintptr_t)((ptr) + 1))
int test(int *an_int) {
*second = 1;
if (ADDR_AFTER(first) == (uintptr_t)an_int) {
// ubsan does not like this.
*an_int = 2;
}
return *second;
}
int first[1] = {0}, second[1] = {0};
int main() {
if (ADDR_AFTER(first) == (uintptr_t)second) {
printf("test: %d\n", test(second));
printf("x: %d y: %d\n", *first, *second);
}
}
Run Code Online (Sandbox Code Playgroud)
我绝不会直接比较两个指向不同对象的指针(因为我将它们转换为uintptr_t第一个)。我创建了一个指向数组末尾一位的指针(这是合法的),但我从未取消引用该指针。据我所知,这应该不打印任何内容,或者打印:
测试:2 x:0 y:2
当优化为或更低时,它会打印在 Clang 上-O1。-O2然而,在 处,它打印:
测试:1 x:0 y:2
它将-O2 -fsanitize=undefinedthis 打印到标准输出:
测试:2 x:0 y:2
以及 stderr 的以下内容:
运行时错误:存储到地址 0x000000cd9efc 时,空间不足以容纳“int”类型的对象 0x000000cd9efc:注意:指针指向这里 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
an_int并引用对in的赋值test。这实际上是未定义的行为,还是 Clang 中的一个错误?
你的代码没有任何无效的地方,编译器是错误的。如果删除不必要的 ADDR_AFTER 检查test(),代码将按预期运行,不会出现 UBSan 错误。如果您在启用优化且没有 UBSan 的情况下运行它,您会得到错误的输出(test=1,应该是 2)。
ADDR_AFTER(first) == (uintptr_t)an_int内部代码的一些问题test()使得 Clang 在使用-O2.
我测试过,Apple clang version 11.0.3 (clang-1103.0.32.62)但看起来 Clang 13 和当前的主干也有这个 bug: https: //godbolt.org/z/s83ncTsbf - 如果你将编译器更改为任何版本的 GCC,你会看到它可以返回 1 或 2 main(),而 Clang 始终返回 1 ( mov eax, 1)。
您可能应该为此提交一个 Clang bug。
| 归档时间: |
|
| 查看次数: |
247 次 |
| 最近记录: |