c - c - 应该未定义的动作看起来非常“定义”。为什么?
问题描述
我知道在 C 中你可能会写超出分配内存的末尾,而不是崩溃这只会导致未定义的行为,但不知何故经过多次测试,即使使用循环和其他变量,输出总是完全一样预期的。
具体来说,我一直在写一个超出 malloc(1) 范围的整数。
int *x = malloc(1);
*x = 123456789;
它足够小,可以放入 4 个字节(我的编译器警告我它会溢出它太大,这是有道理的),但仍然明显大于 1 个字节,但它仍然以某种方式工作。我无法运行一个测试,它要么以非常“定义”的方式工作,要么立即出现段错误。这样的测试包括反复重新编译和运行程序,输出 x 的值,尝试用一个巨大的数组覆盖它,并尝试用一个长度为 0 的数组覆盖它,超出它的边界。
看到这个后,我立即去尝试编辑一个字符串文字,它应该是只读的。但不知何故,它奏效了,而且似乎也很一致。
有人可以推荐一个我可以用来证明未定义行为的测试吗?我的编译器(Windows 10 上的 Mingw64)是否以某种方式弥补了我认为的愚蠢?鼻恶魔在哪里?
解决方案
未定义行为的标志之一是相同的代码在不同的编译器或不同的编译器设置上可能表现不同。
鉴于此代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *x = malloc(1);
x[100000] = 123456789;
return 0;
}
如果我在本地机器上编译-O0
并运行它,代码会出现段错误。如果我用 编译-O3
,它不会。
[dbush@centos72 ~]$ gcc -O0 -Wall -Wextra -o x1 x1.c
[dbush@centos72 ~]$ ./x1
Segmentation fault (core dumped)
[dbush@centos72 ~]$ gcc -O3 -Wall -Wextra -o x1 x1.c
[dbush@centos72 ~]$ ./x1
[dbush@centos72 ~]$
当然,这只是在我的机器上。你的可能会做一些完全不同的事情。
推荐阅读
- javascript - VBA Web 自动化从 HTML 下拉列表中选择下拉值
- reactjs - 反应中的嵌入式地图
- python - 对于 n 的什么值,g(47,n) 会返回 5?
- java - 从 YAML 加载环境变量到 java
- variables - TCL:使用命名空间名称变量
- javascript - 如何在 JavaScript 中创建一个有状态的、类似队列的函数?
- javascript - 我无法在 if 语句中停止 Interval(不和谐 VoiceState)
- scheduling - 有人可以解释优先 Q 算法吗
- python - 什么是“软关键字”?
- php - 如何在 debian 10(buster) 中配置 apache 2.4 和 laravel 8