Бесплатный двойной указатель

Я создал двумерную матрицу, используя двойной указатель:

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

Если ваша матрица не "рваная", то есть все строки имеют одинаковую длину, вы можете рассмотреть следующие вопросы:

  1. Обращаясь к нему вручную, то есть просто обрабатывайте его как одномерный массив значений и сохраняйте отдельное значение width. Для доступа к элементу в (x, y) используйте mat[y * width + x].
  2. Если вы действительно хотите удобство 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 производственный код должен проверять наличие ошибок.