【问题标题】:What happens when you write to memory out of bounds of an array?当您写入超出数组范围的内存时会发生什么?
【发布时间】: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

标签: c arrays gcc


【解决方案1】:

扩展 Patashu 的评论,segmentation faults 当您以与内存权限页面冲突的方式从页面访问内存时发生。换句话说,它们发生在您以不允许的方式访问内存页面时。在您的情况下可能发生的情况是,您仍在访问存储 arg_history 的同一页面内的内存,您显然有权读取和写入。

另一种可能的情况是,您正在处理的内存页之后的内存页具有相同的权限,允许您以相同的方式访问它。

无论如何,这是 C 语言中未定义的行为。尽管您见证了“预期结果”,但这不应该向您表明该程序是正确的。事实上,在这种情况下,越界错误可能会被忽视,如果它不会导致分段错误的话。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 2017-01-24
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多