Бесплатный двойной указатель
Я создал двумерную матрицу, используя двойной указатель:
int** pt; pt = (int*) malloc(sizeof(int)*10);
Я знаю, что указатель освобождается таким образом
free(ptr);
Как мы можем освободить двойной указатель?
Что делать, если мы что-то напечатаем, а потом освободим эту память и выйдем из программы? Заключительная память состоит из того, что мы использовали, или оно будет таким же, как и исходное?
Ответы
Ответ 1
Скажем, у вас есть матрица mat
int** mat = malloc(10 * sizeof(int*));
for (int i=0; i<10; ++i) {
mat[i] = malloc(10 * sizeof(int));
}
тогда вы можете освободить каждую строку матрицы (при условии, что вы правильно инициализировали их заранее):
for (int i=0; i<10; ++i) {
free(mat[i]);
}
затем освободите указатель верхнего уровня:
free(mat);
Для вашего второго вопроса: если вы выделите память и используете ее, вы измените эту память, которая не будет "возвращена", даже если вы ее освободите (хотя вы не сможете получить доступ к ней надежно/переносимо больше).
Примечание: malloc верхнего уровня использует sizeof(int*)
, поскольку вы выделяете указатель на int
s, а не int
- размер int*
и int
не гарантирован то же самое.
Ответ 2
Если ваша матрица не "рваная", то есть все строки имеют одинаковую длину, вы можете рассмотреть следующие вопросы:
- Обращаясь к нему вручную, то есть просто обрабатывайте его как одномерный массив значений и сохраняйте отдельное значение
width
. Для доступа к элементу в (x, y) используйте mat[y * width + x]
.
- Если вы действительно хотите удобство
mat[y][x]
, вы можете улучшить его, выполнив один вызов malloc()
, который выделяет как массив указателей, так и все строки, а затем инициализирует указатели так, чтобы они указывали на каждую строку. Это имеет то преимущество, что все это может быть бесплатным: редактировать одним вызовом free(mat);
.
Второй подход будет выглядеть примерно так:
double ** matrix_new(size_t width, size_t height)
{
double **p = malloc(height * sizeof *p + width * height * sizeof **p);
double *e1 = (double *) (p + height);
size_t i;
for(i = 0; i < height; ++i)
p[i] = e1 + i * width;
return p;
}
Примечание: вышеприведенное не протестировано, и перед использованием p
производственный код должен проверять наличие ошибок.