Нарушение доступа для 2D-массива с использованием указателей

Я пытаюсь создать 2D динамический массив с помощью указателей:

int** Grid;
Grid = new int*[5];
for (int i=0;i<5;i++) { Grid[i] = new int[5]; }
std::cout << Grid[4][300] << std::endl; // output: -17891602
std::cout << Grid[5][0] << std::endl; // access violation

Мне нужен массив определенного размера, поэтому я не использую статический массив. Как вы можете видеть, хотя я делаю массив 5x5, отладчик не дал ошибку при попытке прочитать Grid [4] [300]. Может кто-нибудь, пожалуйста, просветит меня, почему это так?

Это только кажется для второго измерения. (Попытка прочитать Grid [5] [0] даст ошибку нарушения прав доступа) Исправьте меня, если я ошибаюсь, но технически я действительно создаю массив указателей?

Я ожидаю исключения для Grid [5] [0]. То, чего я действительно не понимаю, - это почему нет ошибки для Grid [4] [300]. Может ли кто-нибудь посоветовать мне, как мне получить динамический массив, скажем, размер 5x5?

3 ответа

В c и c++ отсутствует ошибка компиляции, а также ошибка времени выполнения, если вы пытаетесь получить доступ к более крупному индексу, чем объявлено Например.

int a [10]; std :: cout << a [20]; <span>//будет печатать некоторую стоимость мусора</span>

Итак, это ответ на вопрос, почему std :: cout << Grid [4] [300] << std :: endl; дает вывод: -17891602, поскольку второе измерение представляет собой просто массив целых чисел.

Если вы объявляете массив указателей и пытаетесь получить доступ к большему индексу, тогда вы получите либо ошибку нарушения доступа, либо ошибку сегментации во время выполнения Например.

int * a; a = новый int [5]; std :: cout << a [20]; <span>//приведет к ошибке сегментации</span>

Итак, это отвечает на вопрос, почему std :: cout << Grid [5] [0] << std :: endl; или любое значение в первом размере, превышающем объявленное значение, приведет к ошибке, поскольку первое значение должно быть указателем на какое-либо правовое местоположение, содержащее целочисленное значение Но при попытке получить доступ к большему индексу, который может привести к ошибке, которая будет незаконным адресом, что приведет к ошибке сегментации. Надеюсь это поможет.


Проблема в том, что массив также принимает значение 0. Таким образом, самое первое пространство памяти в массиве будет [0] [0], если вы инициализировали его с помощью for (int я = 0; я < Size; ++i)

Рассмотрим этот код:

#include <iostream>

using namespace std;

int main () {
 int Size = 5;
 int **Grid;
 Grid = new int* [Size];
 for (int i = 0; i < Size; ++i)
 Grid[i] = new int [Size];

 for (int i = 0; i < Size; ++i)
 for (int j = 0; j < Size; ++j)
 cin >> Grid[i][j];

 cout << Grid[4][4];
 return 0;
}
</iostream>

Если вы поместите это в свою среду IDE и скомпилируете ее, она должна напечатать значение самого последнего элемента. Это потому, что у вас есть следующие места массива:

Grid[0][0];
Grid[0][1];
Grid[0][2];
Grid[0][3];
Grid[0][4];
...
Grid[4][4];

Также имейте в виду при динамическом распределении любого массива, вы также должны предоставить delete [].

Таким образом, код, который я разместил, будет выглядеть так:

#include <iostream>

using namespace std;

int main () {
 int Size = 5;
 int **Grid;
 Grid = new int* [Size];
 for (int i = 0; i < Size; ++i)
 Grid[i] = new int [Size];

 for (int i = 0; i < Size; ++i)
 for (int j = 0; j < Size; ++j)
 cin >> Grid[i][j];

 cout << Grid[4][4];

 for (int i = 0; i < Size; ++i)
 delete [] Grid[i];
 delete [] Grid;
 return 0;
}
</iostream>

Это потому, что вы работаете со стеком. → http://ru.wikipedia.org/wiki/Stack_%28abstract_data_type%29

Надеюсь, это прояснит некоторые вещи для вас. Удачи!


Вы никогда не инициализировали Grid [5], в вашем for-loop вы проверили i < 5. Если я меньше 5, он никогда не будет использоваться как 5 внутри вашего цикла.

Просто помните, что массивы подсчитывают 0 как позицию.

Это означает, что int arr[5] может быть проиндексирован только с 0-4, что-то большее или меньшее приведет к нарушению доступа.

Причина, по которой [300] не бросает нарушение доступа, заключается в том, что вы указали указатель, а не определенный массив.

Кроме того, не забудьте инициализировать значения в вашем массиве (с вероятностью 0). Возможно, вам не нужны неожиданные цифры, например -1994021 отображаемые в ваших данных. memset очень хорош в этом.

licensed under cc by-sa 3.0 with attribution.