Бесплатный двумерный массив. Статический указатель

У меня есть статический указатель

   static int **2dArr;

а затем я выделяю память для 2d массива. Как я могу освободить эту память и заменить ее другим массивом?

   //////////////////////////////////////////////////////////////////////////
  void func(int **arr) {
    int i,j,k,tmp;
    int **destMatrix = NULL;
destMatrix = (int**) malloc(N * sizeof(int *));

if ((destMatrix == NULL)) {
    fprintf(stderr, "out of memory\n");
    exit(2);
}

for (i = 0; i < N; i++) {
    destMatrix[i] = (int*) malloc(N * sizeof(int));

    if (destMatrix[i] == NULL) {
        fprintf(stderr, "out of memory\n");
        exit(2);
    }
}



for(i = 0; i < N; ++i) {
    free(arr[i]);
}
free(arr);
arr = NULL;
arr = destMatrix;

}
  //////////////////////////////////////////////////////////////////////////
  int main() {
   2dArr = (int**) malloc(N * sizeof(int *));
   if (2dArr== NULL) {
    fprintf(stderr, "out of memory\n");
    exit(2);
     }


for (i = 0; i < N; i++) {
    2dArr[i] = (int*) malloc(N * sizeof(int));

    if (2dArr[i] == NULL) {
            fprintf(stderr, "out of memory\n");
            exit(2);
    }
}
    func(2dArr);
    // try to print new array, access violation
 }

Освобождаю память и пытаюсь заменить указатель. Но тогда у меня есть нарушение доступа. Как я могу сделать это правильно?


person user565447    schedule 15.01.2012    source источник
comment
Прокрутите и освободите каждый указатель во втором измерении, затем освободите основной указатель   -  person Seth Carnegie    schedule 15.01.2012
comment
Освобождаю память и пытаюсь заменить указатель — вы освобождаете память, но не заменяете указатель. Вы только заменяете его копию (переменная arr в func). Исходный указатель (как бы он ни назывался на самом деле, он не может быть 2dArr, это не настоящий идентификатор) остается неизменным и указывает на уже освободившуюся память.   -  person n. 1.8e9-where's-my-share m.    schedule 15.01.2012


Ответы (3)


Пара вещей:

  • Вам нужно передать аргумент по ссылке в func: void func(int ***arr) {
  • Затем измените способ освобождения вещей: free((*arr)[i]); и free(*arr);.
  • и, наконец, измените способ переназначения обр: *arr = destMatrix;
  • также не называйте переменные, начинающиеся с цифры - это не работает.
  • (также у вас было ++i вместо i++ в цикле for в конце func ) это на самом деле не имеет значения - см. комментарий ниже

Я устранил эти проблемы с помощью Valgrind. , проверьте это.

Рабочий код ниже:

#include <stdio.h>
#include <stdlib.h>

#define N 10 
//////////////////////////////////////////////////////////////////////////
void func(int ***arr) {
  int **destMatrix = NULL;
  destMatrix = malloc(N * sizeof(int *));

  if ((destMatrix == NULL)) {
    fprintf(stderr, "out of memory\n");
    exit(2);
  }

  int i;
  for (i = 0; i < N; i++) {
    destMatrix[i] = malloc(N * sizeof(int));

    if (destMatrix[i] == NULL) {
      fprintf(stderr, "out of memory\n");
      exit(2);
    }
  }

  for(i = 0; i < N; i++) {
    free((*arr)[i]);
  }
  free(*arr);
  *arr = destMatrix;

}
//////////////////////////////////////////////////////////////////////////
int main() {
  int **tdArr = malloc(N * sizeof(int *));
  if (tdArr== NULL) {
    fprintf(stderr, "out of memory\n");
    exit(2);
  }

  int i;
  for (i = 0; i < N; i++) {
    tdArr[i] = malloc(N * sizeof(int));

    if (tdArr[i] == NULL) {
      fprintf(stderr, "out of memory\n");
      exit(2);
    }
  }

  func(&tdArr);
  // try to print new array, does not get access violation

  //assign numbers 0-99
  int j;
  for (i=0; i<N; i++){
    for (j=0; j<N; j++){
      tdArr[i][j] = i*10+j;
    }
  }
  //print numbers
  for (i=0; i<N; i++){
    for (j=0; j<N; j++){
      printf("%d\n", tdArr[i][j]);
    }
  }

  //free internal arrays
  for (i=0; i<N; i++){
    free(tdArr[i]);
  }
  //free outer array
  free(tdArr);

  return 0;
}
person Community    schedule 15.01.2012
comment
Какое значение имеет последнее наблюдение? - person another.anon.coward; 15.01.2012
comment
@anoner.anon.coward, если вы ++i вместо i++ в: for(i = 0; i < N; i++) { free((*arr)[i]); } Тогда вы пренебрегаете свободным индексом 0. (как добавить новые строки в комментарии?) - person devictories; 15.01.2012
comment
Неа. Вы освобождаете их всех. см. это. Принцип работы for заключается в том, что после инициализации и проверки условия тело выполняется до изменения значения. См. это для получения дополнительных разъяснений. - person another.anon.coward; 15.01.2012

Я не совсем уверен, что вы пытаетесь здесь сделать, но имейте в виду, что утверждение

arr = destMatrix;

в func только устанавливает локальную копию вашего указателя на destMatrix. Вернувшись в main (и глобально), 2dArr (или как вы его на самом деле назвали, поскольку, как заметил @n.m., это недействительный идентификатор) по-прежнему имеет исходное значение malloced, даже если вы успешно освободили все указатели в func. Если вы попытаетесь использовать или освободить этот указатель (или старые указатели, на которые он все еще [вероятно] указывает) в другом месте, вы можете получить различные ошибки. (В этом случае радуйтесь, что вы получаете ошибки — вместо этого вы могли бы молча уничтожать память, от которой зависит какой-то другой процесс.) Если вы собираетесь изменить 2dArr в func, вам нужно объявить

void func(int ***arr);

и назовите его с

func(&2dArr);

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

free((*arr)[i]);
person Joshua Green    schedule 15.01.2012

В func вы освобождаете память для статической переменной 2darr, и похоже, что вы намереваетесь установить ее в destMatrix, но вы только устанавливаете копию переменной указателя ввода в func.

Если вы измените на void func(int **& arr), то вы можете установить 2darr, это передача int** по ссылке вместо значения.

person Chris O    schedule 15.01.2012