访问字符数组中的不可用内存位置(超出范围值)

时间:2017-04-29 00:59:25

标签: c++ c++11

我有一段代码:

#include <iostream>
using namespace std;

int main(){

    char a[5][5] = {{'x','y','z','a','v'},{'d','g','h','v','x'}};

    for(int i=0; i<2; i++){
        for(int j = 0; j<6; j++)
        {
            cout << a[i][j];
        }
    }

    return 0;

}

正如您所看到的那样,第一维和第二维各有5个元素。使用double for循环,我只是打印为变量a初始化的内容。

int“j”的大小,因为它会显着增加输出变化。

为什么会这样?

指针是否是解决方案?如果有,怎么样?如果没有我们可以做些什么来避免由于这种不正确的访问导致的运行时错误?

1 个答案:

答案 0 :(得分:1)

您可能会将此问题视为Java中的越界错误,其中严格定义了行为:您将获得ArrayIndexOutOfBoundsException,程序将立即终止,除非异常抓住并处理。

在C ++中,这种越界错误是未定义的行为,这意味着允许编译器做任何它认为会达到最佳性能的愚蠢行为。一般来说,这会导致编译器只是盲目地执行它将对入站的数组访问执行的相同指针算法,无论内存是否有效。

在您的情况下,因为您已经分配了25 char个内存,所以您至少会在i * 5 + j >= 25之前访问有效内存(在大多数环境中,UB可以承受),此时可能发生任何事情:

  • 你可以从堆栈中获取垃圾数据
  • 您可能会因分段错误(Windows / Visual Studio中的访问冲突)而导致程序崩溃
  • 循环可以拒绝在您希望终止的索引处终止。

最后一个是一个令人难以置信的错误:如果正在进行积极的循环优化,当你在代码中犯这样的错误时,你可能会得到一些very odd behavior

你编写的代码中几乎可以肯定的是,第一点:尽管你为25 char分配了空间,但你只定义了其中10个的内容,这意味着除了那些之外的任何访问前10个将调用另一种未定义的行为(访问未初始化的变量),绝大多数时候,它会导致它们的值被填入,无论是在该内存空间之前是什么。使用变量。