Ваши две основные проблемы:
- Вам не удалось проверить возврат каждого распределения, поэтому
malloc
мог потерпеть неудачу и у вас не было бы возможности узнать;и - После выделения памяти для ваших целочисленных значений вы не можете инициализировать память, оставляя память, в которой хранятся все значения мусора, которые присутствовали в этом месте памяти (вы можете, и в случае ваших целочисленных распределений,используйте
calloc
для одновременного выделения и инициализации или memset
для того же)
Ваша попытка получить доступ к matrix[2][3]
до того, как free()
просто получит доступ к неинициализированному 4-байты памяти, содержащие биты, которые там были. Ваша попытка доступа к matrix[2][3]
после free()
вызывает Неопределенное поведение . После free()
вы больше не можете получить доступ к освобожденной памяти.
Если вы выделяете, вы должны проверить ... Это не вопрос , если malloc
можетне удается вернуть NULL
, это , когда malloc
не может вернуть NULL
. Чтобы обработать случай сбоя, вы всегда должны проверять возврат функции распределения (как вы делаете с каждой input функцией), которую вы используете. Это просто, если malloc
возвращает NULL
, выделение не выполнено. Так что просто проверьте, например,
int **creatematrix (int row, int col)
{
int **m = malloc (row * sizeof *m);
if (!m) { /* if you allocate -- you must VALIDATE */
perror ("malloc-m");
return NULL;
}
for (int x = 0; x < row; x++) {
if (!(m[x] = malloc (col * sizeof *m[x]))) { /* ditto */
perror ("malloc-m[x]");
while (x--) /* on error free any allocated memory */
free (m[x]);
free (m); /* before returing NULL */
return NULL;
}
}
return m;
}
( примечание: , прежде чем возвращать NULL
, вы должны free()
любую память, выделенную для этой точки, чтобы предотвратить утечку памяти при возвратеNULL
)
В вашей вызывающей функции (main()
здесь) вам необходимо проверить возвращение вашей функции creatematrix
, чтобы определить успех / неудачу выделения - до Вы используете память, например,
int main (void) {
int **matrix,
rows = 5,
cols = 6;
if (!(matrix = creatematrix (rows, cols))) /* VALIDATE allocations */
exit (EXIT_FAILURE);
for (int i = 0; i < rows; i++) { /* loop initializing all values */
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
printf (" %3d", matrix[i][j]); /* output all values */
}
putchar ('\n');
}
freematrix (matrix, rows); /* free all allocated memory */
}
Теперь вы можете free()
всю память (что, кроме опечатки 'z'
вместо 'x'
, вы делали правильно). В целом, вы можете сделать:
#include <stdio.h>
#include <stdlib.h>
int **creatematrix (int row, int col)
{
int **m = malloc (row * sizeof *m);
if (!m) { /* if you allocate -- you must VALIDATE */
perror ("malloc-m");
return NULL;
}
for (int x = 0; x < row; x++) {
if (!(m[x] = malloc (col * sizeof *m[x]))) { /* ditto */
perror ("malloc-m[x]");
while (x--) /* on error free any allocated memory */
free (m[x]);
free (m); /* before returing NULL */
return NULL;
}
}
return m;
}
void freematrix (int **m, int row)
{
for (int x = 0; x < row; x++)
free (m[x]);
free (m);
}
int main (void) {
int **matrix,
rows = 5,
cols = 6;
if (!(matrix = creatematrix (rows, cols))) /* VALIDATE allocations */
exit (EXIT_FAILURE);
for (int i = 0; i < rows; i++) { /* loop initializing all values */
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
printf (" %3d", matrix[i][j]); /* output all values */
}
putchar ('\n');
}
freematrix (matrix, rows); /* free all allocated memory */
}
Пример использования / вывода
$ ./bin/freematrix
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
18 19 20 21 22 23
24 25 26 27 28 29
Использование памяти / проверка ошибок
В любом написанном вами коде, который динамически распределяет память, у вас есть 2 обязанностей относительно любого выделенного блока памяти: (1) всегда сохраняйте указатель на начальный адрес для блокапамяти, так, (2) он может быть освобожден , когда он больше не нужен.
Крайне важно, чтобы вы использовали программу проверки ошибок памяти, чтобы убедиться, что вы не пытаетесь получить доступ к памяти илиписать за пределами / за пределами выделенного блока, пытаться прочитать или основать условный переход на неинициализированном значении и, наконец, подтвердить, что вы освобождаете всю выделенную память.
Для Linux valgrind
- нормальный выбор. Для каждой платформы есть похожие проверки памяти. Все они просты в использовании, просто запустите вашу программу через нее.
$ valgrind ./bin/freematrix
==17080== Memcheck, a memory error detector
==17080== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==17080== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==17080== Command: ./bin/freematrix
==17080==
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
18 19 20 21 22 23
24 25 26 27 28 29
==17080==
==17080== HEAP SUMMARY:
==17080== in use at exit: 0 bytes in 0 blocks
==17080== total heap usage: 6 allocs, 6 frees, 160 bytes allocated
==17080==
==17080== All heap blocks were freed -- no leaks are possible
==17080==
==17080== For counts of detected and suppressed errors, rerun with: -v
==17080== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Всегда подтверждайте, что вы освободили всю выделенную память и что ошибок памяти нет.
Посмотрите вещии дайте мне знать, если у вас есть дополнительные вопросы.