【发布时间】:2013-04-19 01:04:48
【问题描述】:
在最近的一个测试问题中,我被要求打印以下程序的输出。我得到了正确的答案,但是这个程序给我带来了极大的精神痛苦,因为我不知道写入超出数组范围的内存时会发生什么行为。
这是有问题的程序,cmets 是我的笔记:
#include <stdio.h>
#define MAX 4
void RecordArgs(int x);
int main()
{
RecordArgs(1);
RecordArgs(7);
RecordArgs(-11);
return 0;
}
void RecordArgs(int x)
{
static int i = 0;
int call_count = 0;
int arg_history[MAX] = {0};
if (call_count == MAX)
{
# call_count is not static and is initialized to 0 on each call
# as a result, under no circumstance can call_count == MAX and
# this printf is never executed
printf("Too many calls to RecordArgs\n");
}
else
{
# index out of bounds on second/third call (i + call_count will be 4??)
arg_history[i + call_count] = x;
++call_count;
++i;
for (i = 0; i < MAX; ++i)
printf("%d ", arg_history[i]);
printf("\n");
}
}
以及预期的输出:
1 0 0 0
0 0 0 0
0 0 0 0
第二次和第三次调用 RecordArgs 时,7 和 -11 值会写入哪里?我尝试在不同的设置下编译它,看看我是否可以让它两次写入它不应该写入的东西,但我尝试过的一切都导致了没有任何段错误的确切输出。
【问题讨论】:
-
越界读取或写入数组是未定义的行为。未定义行为是 C/C++ 中的一个特定术语,意思是“编译器可以决定发生什么,无论它想要什么”。在实践中,根据数组的放置位置(堆栈?堆?等),它将访问它已分配的程序内存的其他部分、随机未初始化的数据或因访问冲突而崩溃。最重要的是,它在你的程序中所做的事情可能会随着编译和计算机的不同而变化——也就是说,它会在最意想不到的时候做最糟糕的事情。
-
问了非常相似的问题here