Как правильно освободить динамически выделенную память для массива указателей на int - PullRequest
0 голосов
/ 29 декабря 2018

Мне нужно знать, правильно ли я использовал free() при попытке освободить динамически выделенную память для массива указателей на int.

Мой код изменен из фрагмента кода одной из моих книги это начало программы, которая запрашивает показания температуры для трех городов.

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

int main()
{
  int ctr, num, num2 = 0, ctr2 = 0;
  int* temps[3];
  for(ctr = 0; ctr < 3; ctr++)
  {
     puts("how many readings for the city?");
     scanf(" %d", &num);
     temps[ctr] = (int*)malloc(num * sizeof(int));
     num2 += num;
     while(ctr2 < num2)
     {
         puts(" what is reading? ");
         scanf(" %d", &temps[ctr][ctr2]);
         printf("echo: %d ", temps[ctr][ctr2]);

         ctr2++;
     }
  }

  for(ctr = 0; ctr < 3; ctr++)
  {
      free(temps[ctr]);
  }

  getchar();
  getchar();

  return (0);
}

Я знаю, что указатель, которому назначается память с помощью malloc (), может иметь значения, назначенные и доступные через комбинацию цикла ииндексы массива.Следовательно, я назначил значения из пользовательского ввода, используя индексы двумерного массива, и мне нужно знать, правильно ли я использовал free.Я знаю, что это крайне неаккуратное кодирование, и я просто стараюсь правильно понять, чтобы предотвратить возможные утечки памяти.

Ответы [ 3 ]

0 голосов
/ 30 декабря 2018

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

Следующий код проверит все случаи:

scanf(" %d", &num);

/*
 * check here if the value of ctr in non-negative and in the appropriate range
 */

temps[ctr] = (int*)malloc(num * sizeof(int));
if (temps[ctr] == NULL) {
      printf ("Memory allocation failed\n");
      /* 
       * appropriate error handling
       */
}

Кроме того, проверьте, когда вы освобождаете память, чтобы она была более безопасной.

for(ctr = 0; ctr < 3; ctr++)
{
      if(temps[ctr]) {
           free(temps[ctr]);
      }
}

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

num2 += num;
while(ctr2 < num2)
 {
     puts(" what is reading? ");
     scanf(" %d", &temps[ctr][ctr2]);
     printf("echo: %d ", temps[ctr][ctr2]);

     ctr2++;
 }

Здесь, если значение num было 20 на первой итерации, то на второй итерации вы в конечном итоге получите входные данные, начиная с temps[1][20] и принимая значение numво второй итерации, равной 5, вы выделили всего 5 * sizeof(int)), поэтому очевидно, что вы выходите за пределы, когда пытаетесь получить доступ к temps[1][20].

0 голосов
/ 30 декабря 2018

Пожалуйста, дайте мне знать, если следующий код будет считаться приемлемым:

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








int main()
{
  int ctr, num, ctr2 = 0;
  int * temps[3];
  for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
  {
     puts("how many readings for the city?");
 if (!scanf(" %d", &num) || num <= 0) { printf("wrong number\n"); exit(1); }
 temps[ctr] = (int *) malloc(num * sizeof(*temps[ctr]));

     while(ctr2 < num)
     {


     puts(" what is reading? ");
     scanf(" %d", &temps[ctr][ctr2]);
     printf("echo: %d ", temps[ctr][ctr2]);

     ctr2++;
     }
     ctr2 = 0;




  }

  for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
  {
      free(temps[ctr]);
  }

  getchar();
  getchar();

  return (0);


 }
0 голосов
/ 29 декабря 2018

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

for(ctr = 0; ctr < 3; ctr++)

Просто убедитесь, что temps может содержать по крайней мере 3 элемента, что имеет место,и что num не равно нулю или не определено (тестовое возвращаемое значение scanf & значение num).Вы можете использовать формулу sizeof в вашем случае, чтобы избежать жесткого кодирования значения, только потому, что у вас есть массив указателей, а не указателей на указатели.

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

for(ctr = 0; ctr < (int)(sizeof(temps)/sizeof(*temps)); ctr++)
  {
     puts("how many readings for the city?");
     if (!scanf(" %d", &num) || num <= 0) { printf("wrong number\n"); exit(1); } // or better error handling
     temps[ctr] = malloc(num * sizeof(*temps[ctr]));

Вы можете все еще получить ошибку сегментации при вызове free, если вы повреждаете память при заполнении ваших массивов (комментарий предполагает, что это происходит, поскольку num2 растет и растет),Если вы получаете такие ошибки, запустите ваш код с помощью valgrind или просто выполните выделения / освобождения (а не остальные), чтобы найти, какая часть кода вызывает проблему.

...