C: Правильно освобождающая память многомерного массива

Не ожидать. Выберите один и пойдите с ним. Все системы будут иметь свои плюсы и минусы. Ваше питание могло выйти, Вы, компьютер украден, или Вы забываете отменять существенное изменение, и весь Ваш код пожарен, в то время как Вы ожидаете для наблюдения, кто одерживает победу.

38
задан Community 23 May 2017 в 12:10
поделиться

5 ответов

Задача junitreport использует XSLT для создания отчета из файлов XML, созданных задачей junit .

Вы можете настроить вывод, указав свой собственный XSLT, используя атрибут styledir вложенного элемента report :

<!-- use reportstyle/junit-frames.xsl to produce the report -->
<report styledir="reportstyle" format="frames" todir="testreport"/>

Для настройки вывода можно было бы сделать копию XSLT по умолчанию и измените ее. Или вы можете поискать альтернативный XSLT, который легче настроить для ваших целей.

Для небольших изменений может быть проще просто импортировать XSLT по умолчанию и переопределить любые шаблоны, которые вам нужно настроить. Например, чтобы добавить столбец для каждого теста, вам нужно будет переопределить шаблон, который создает заголовок таблицы, и шаблон, который создает строку таблицы. Ниже, необходимые бесплатные () звонки должны быть включены, поэтому я постараюсь уточнить, что люди пытаются понять и почему.

Начиная с основ, чтобы освободить выделенную память используя malloc () , вы просто вызываете free () точно с указателем который вам дал malloc () . Итак, для этого кода:

int **a = malloc(m * sizeof(int *));

вам нужно сопоставление:

free(a);

и для этой строки:

a[i]=malloc(n * sizeof(int));

вам нужно сопоставление:

free(a[i]);

внутри аналогичного цикла.

Здесь усложняется порядок, в котором это должно произойти. Если вы вызываете malloc () несколько раз, чтобы получить несколько разных фрагментов памяти, как правило, не имеет значения, в каком порядке вы вызываете free () , когда ты покончил с ними. Однако порядок здесь важен для очень конкретная причина: вы используете один фрагмент памяти malloc ed для хранения указатели на другие фрагменты памяти malloc ed. Поскольку вы не должны пытаться читать или записывать память после того, как вы вернули ее с помощью free () , это означает, что вам придется освободить фрагменты с помощью их указатели хранятся в a [i] до того, как вы освободите сам фрагмент a . Отдельные фрагменты с указателями, хранящиеся в a [i] , не зависят от каждого other, и поэтому может быть free d в любом порядке.

Итак, сложив все это вместе, мы получаем следующее:

for (i = 0; i < m; i++) { 
  free(a[i]);
}
free(a);

И последний совет: при вызове malloc () , подумайте об изменении этих:

int **a = malloc(m * sizeof(int *));

a[i]=malloc(n * sizeof(int));

на:

int **a = malloc(m * sizeof(*a));

a[i]=malloc(n * sizeof(*(a[i])));

Что это делает? Компилятор знает, что a является int ** , поэтому он может определите, что sizeof (* a) совпадает с sizeof (int *) . Однако если позже вы передумаете и захотите char s или short s или long s или все, что есть в вашем массиве вместо int s, или вы адаптируете этот код для дальнейшего использования использовать в другом, вам нужно будет заменить только один оставшийся ссылка на int в первой цитируемой строке выше и все остальное автоматически встанет на место для вас. Это убирает вероятность незамеченных ошибок в будущем.

Удачи!

67
ответ дан 27 November 2019 в 03:25
поделиться

Отмените именно то, что вы выделили:

  for (i = 0; i < m; i++) { 
      free(a[i]);
  }
  free(a);

Обратите внимание, что вы должны сделать это в обратном порядке, из которого вы изначально выделяли память. Если вы сначала выполнили free (a) , то a [i] будет обращаться к памяти после того, как она будет освобождена, что является неопределенным поведением.

8
ответ дан 27 November 2019 в 03:25
поделиться

Вам нужно повторить итерацию по массиву и выполнить столько освобождений, сколько mallocs для указанной памяти, а затем освободить массив указателей.

for (i = 0; i < m; i++) { 
      free (a[i]);
}
free (a);
4
ответ дан 27 November 2019 в 03:25
поделиться

Напишите операторы распределения в точном обратном порядке, меняя имена функций, и все будет в порядке.

  //Free the arrays
  for (i = m-1; i >= 0; i--) { 
      free(a[i]);
  }

  free(a);

Конечно, вам не нужно освобождать в том же обратном порядке. Вам просто нужно следить за тем, чтобы освободить одну и ту же память ровно один раз и не «забывать» указатели на выделенную память (как это было бы, если бы вы сначала освободили a ). Но освобождение в обратном порядке - хорошая практическая роль для решения последнего.

Как указано в litb в комментариях, если выделение / освобождение имело побочные эффекты (например, new ] / delete в C ++), иногда обратный порядок освобождения был бы более важен, чем в этом конкретном примере.

3
ответ дан 27 November 2019 в 03:25
поделиться

Я бы назвал malloc () и free () только один раз:

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

int main(void){
  int i, m = 5, n = 20;
  int **a = malloc( m*(sizeof(int*) + n*sizeof(int)) );

  //Initialize the arrays
  for( a[0]=(int*)a+m, i=1; i<m; i++ ) a[i]=a[i-1]+n;

  //...do something with arrays

  //How do I free the **a ?
  free(a);

  return 0;
}
1
ответ дан 27 November 2019 в 03:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: