Проблема с массивом динамичных массивов

`#include <iostream>

using namespace std;

void PrintDiagonalArray(int** f, int n, int k) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i - j == k) {
                cout << f[i][j] << " ";
            }
        }
    }
}
void printArray(int** f, int n) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << f[i][j] << "\t";
        }
        cout << "\n";
    }
}

void fillArray(int** f, int n) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            f[i][j] = i + j;
        }
    }
}
int main() {
    const int n = 10;
    int* b = new int[n];
    int** bb = new int* [n];
    for (int i = 0; i < n; i++) bb[i] = b + i * n;
    fillArray(bb, n);
    printArray(bb, n);
    delete bb;
    delete b;
}

` Проблема в том, что он ведет себя неопределенно, то заполняет все как надо, при втором запуске, вообще ничего не выводит, в некоторых адресах может хранится мусор.

введите сюда описание изображения


Ответы (1 шт):

Автор решения: Chorkov

Вы пытаетесь заполнить квадратную матрицу n*n (10 * 10 = 100) элементов. В строке int* b = new int[n]; вы выделили место по 10 элементов. Далее, выражение b + i * n, для i>0, будет указывать на область за пределами выделенного массива. После это выражение попадет в fillArray, где по нему будет совершена запись данных - это неопределенное поведение (UB). Далее программа имеет право делать что угодно.

Есть два пути исправления, в зависимости от ого хотите ли вы хранить данные одним блоком, или отдельными блоками для каждой строки.

  1. С-путь: код будет потенциально быстрее
int* b = new int[n * n];  /// и далее никаких изменений
  1. С++ - путь: код будет более гибким к последующим изменениям, поскольку будет понятно, кто является владельцем данных для каждого конкретного указателя, включая указатели в массиве bb.
int main() {
    const int n = 10;
    //int* b = new int[n];
    int** bb = new int* [n];
    for (int i = 0; i < n; i++) bb[i] = new int[n];
    fillArray(bb, n);
    printArray(bb, n);
    for (int i = 0; i < n; i++) delete bb[i];
    delete bb;
    //delete b;
}
→ Ссылка