Выделите память на char *** в C

Итак, у меня возникают проблемы с распределением памяти для переменной типа char ***. Моя цель состоит в том, чтобы создать матрицу строк и код, который я сейчас имею для выделения памяти, следующий:

char ***matrix;

matrix = calloc(n*MAX_STR, sizeof(char**));
for(z = 0; z < n; z++) {
    matrix[z] = calloc(n, sizeof(char*));
    for(i = 0; i < MAX_STR; i++) {
        matrix[z][i] = calloc(MAX_STR, sizeof(char));
    }
}

Я успешно выделил память для массива строк, используя это:

char **list;
list = calloc(n, sizeof(char *));
for (j = 0; j < n; j++){
list[j] = calloc(MAX_STR, sizeof(char));
}

но у меня возникают проблемы с матрицей.

Запуск программы с помощью --leak-check = full на Valgrind дает мне следующее сообщение:

==5126== Invalid write of size 8
==5126==    at 0x400B9F: createmat (proj.c:100)
==5126==    by 0x401598: main (proj.c:237)
==5126==  Address 0x5210878 is 0 bytes after a block of size 72 alloc'd
==5126==    at 0x4C2ABB4: calloc (vg_replace_malloc.c:593)
==5126==    by 0x400B52: createmat (proj.c:98)
==5126==    by 0x401598: main (proj.c:237)

Я хотел бы выяснить, как выделить память для этого, так как я все еще новичок, когда дело доходит до управления памятью в C. Любая помощь была бы оценена, спасибо.

EDIT: Предполагается, что в матрице должно храниться n массивов строк, которые соответствуют строкам ввода (они читаются с fgets позже), и каждый массив выделяет любое число слов, которое имеет линия, с каждым словом (чтение, каждая строка) имея при max a MAX_STR количество символов. n - это переменная, считываемая с ввода, а MAX_STR - константа, определенная в программе.

Ответ 1

Предполагая, что вы хотите выделить хранилище для массивов n, каждая из которых содержит строки n, каждая из которых до MAX_STR длинна, в коде есть несколько ошибок

matrix = calloc(n*MAX_STR, sizeof(char**));

должен быть

matrix = calloc(n, sizeof(char**));

и

for(i = 0; i < MAX_STR; i++) {

должен быть

for(i = 0; i < n; i++) {

В более подробной информации

matrix = calloc(n*MAX_STR, sizeof(char**));
for(z = 0; z < n; z++) {

кажется неправильным. Вы выделяете элементы n*MAX_STR, но используете только n из них

matrix[z] = calloc(n, sizeof(char*));
for(i = 0; i < MAX_STR; i++) {

также сомнительно и неверно для n<MAX_STR. (Вы выделяете элементы n, а затем пишите в MAX_STR из них.)

Наконец, в зависимости от того, считаете ли вы, что MAX_STR включить пространство для нулевого терминатора, вам может потребоваться изменить

matrix[z][i] = calloc(MAX_STR, sizeof(char));

к

matrix[z][i] = calloc(MAX_STR+1, 1);

Ответ 2

Матрица массива String или /3D char:

Предположим, что вам нужны матрицы N, каждая матрица может хранить строки R length MAX_STR-1, тогда вы должны выделить ячейку памяти следующим образом:

char ***matrix;

matrix = calloc(N, sizeof(char**)); 
for(z = 0; z < N; z++) { 
    matrix[z] = calloc(R, sizeof(char*));
    for(i = 0; i < R; i++) {
        matrix[z][i] = calloc(MAX_STR, sizeof(char));
    }
}

Его создаст матрица как:

matrix
+-------------------+------------------+-----------------------+
| 0                 | 1                | 2                     |
+-------------------+------------------+-----------------------+        
 |                           |                        |
 ▼                           ▼                        ▼
+--+    +----------+       +--+    +----------+     +--+    +----------+
|0 +---►| MAX_STR  |       |0 +---►| MAX_STR  |     |0 +---►| MAX_STR  |
+--+    +----------+       +--+    +----------+     +--+    +----------+
|1 +---►| MAX_STR  |       |1 +---►| MAX_STR  |     |1 +---►| MAX_STR  |
+--+    +----------+       +--+    +----------+     +--+    +----------+
|2 +---►| MAX_STR  |       |2 +---►| MAX_STR  |*    |2 +---►| MAX_STR  |
+--+    +----------+       +--+    +----------+     +--+    +----------+
|3 +---►| MAX_STR  |       |3 +---►| MAX_STR  |     |3 +---►| MAX_STR  |
+--+    +----------+       +--+    +----------+     +--+    +----------+
|4 +---►| MAX_STR  |       |4 +---►| MAX_STR  |     |4 +---►| MAX_STR  |
+--+    +----------+       +--+    +----------+     +--+    +----------+
|5 +---►| MAX_STR  |       |5 +---►| MAX_STR  |     |5 +---►| MAX_STR  |
+--+    +----------+       +--+    +----------+     +--+    +----------+
|6 +---►| MAX_STR  |       |6 +---►| MAX_STR  |     |6 +---►| MAX_STR  |
+--+    +----------+       +--+    +----------+     +--+    +----------+
|7 +---►| MAX_STR  |       |7 +---►| MAX_STR  |     |7 +---►| MAX_STR  |
+--+    +----------+       +--+    +----------+     +--+    +----------+
 ^        ^ 
 |        |
 |        matrix[z][i]
 matrix[z]

Здесь N = 3 и
   R = 8

Его char 3D-массив размером matrix[N][R][MAX_STR]

Предположим, что если кто-то хочет напечатать строку f, помеченную на диаграмме *, то есть третью строку во втором массиве, тогда он должен индексироваться как

printf("%s",matrix[1][2]);

Хотя ответ принят, я обновляю свой ответ, поэтому он может найти его полезным в будущем

Ответ 3

Как вы уже сказали, вы смогли успешно создать массив строк, используя приведенный ниже код:

char **list;
list = calloc(n, sizeof(char *));
for (j = 0; j < n; j++){
list[j] = calloc(MAX_STR, sizeof(char));
}

Теперь вам нужен массив массивов строк, поэтому он должен быть:

char ***matrix;

matrix = calloc(n, sizeof(char**)); //This creates space for storing the address of 'n' array of strings 
for(z = 0; z < n; z++) { //This loop creates the 'n' array of strings.
    matrix[z] = calloc(n, sizeof(char*));
    for(i = 0; i < n; i++) {
        matrix[z][i] = calloc(MAX_STR, sizeof(char));
    }
}

Итак, в основном, во втором коде вы просто создаете пространство для хранения списков "n". Надеюсь, это ясно.