为了对 C99 和 Rust 进行一些比较,我编写了以下 C 代码,
typedef enum {
NICKLE, DIME, QUARTER, DOLLAR,
} Denom;
static const int cents[] = {
[NICKLE] = 5,
[DIME] = 10,
[QUARTER] = 25,
[DOLLAR] = 100,
};
int main () {
printf( "Result %d\n", cents[DIME] );
}
这按预期工作,现在我想显示越界访问,当我这样做时
typedef enum {
NICKLE, DIME, QUARTER, DOLLAR, ZOD = 20394
} Denom;
我很期待
printf( "Result %d\n", cents[ZOD] );
显示为 cents + ZOD
的访问权限。但事实并非如此。
mov eax, 0
mov esi, eax
lea rdi, str.Result__d ; 0x5570bf1ed020 ; "Result %d\n"
mov eax, 0
call sym.imp.printf ; int printf(const char *format)
为什么要将 esi
设置为 0
,为什么会打印
Result 0
-Wall -Wextra -Wpedantic
也没有错误。 GCC 是否提供管理此行为的标志?它是否知道这是越界的,如果是这样,它是否也不会发出警告(或者是否可以让它发出警告)?
最佳答案
是的,GCC 可以在特定情况下对此发出警告(请参阅@Acorn 的回答)。
有一个运行时未定义行为检查器,-fsanitize=undefined
,如果您执行某些类型的未定义行为(例如访问过去的数组边界),应该会报错。
由于这是未定义的行为,编译器可以自由地做任何它想做的事。这意味着它可以将 esi
设置为零、您的密码的十六进制表示形式或任何其他内容。
关于c - 为什么这不会在 C 中生成越界访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57748788/