【问题标题】:How to properly free dynamically allocated memory for an array of pointers to int's如何为指向 int 的指针数组正确释放动态分配的内存
【发布时间】:2018-12-28 21:06:40
【问题描述】:

我需要知道我在尝试为指向 int 的指针数组释放动态分配的内存时是否正确使用了 free()

我的代码是从我的一本书中的代码 sn-p 修改而来的,它是请求三个城市的温度读数的程序的开始。

#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。我知道这是非常草率的编码,我只是想正确理解 free 以防止任何潜在的内存泄漏。

【问题讨论】:

  • 格式正确的代码不是一个可选的东西。
  • 不管怎样,在这样的程序中,您将返回操作系统,操作系统将回收您使用的所有内存。
  • 看起来不错,除了 malloc 的返回值的无用转换
  • @RobertHarvey 我敢打赌你从来没有拥有过 Amiga :)
  • 不。从没干过。 :)

标签: c malloc free


【解决方案1】:

没关系,因为您使用相同的语句尊重相同数量的分配和释放循环:

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

只要确保temps 至少可以容纳3 个元素,即num 不为零或未定义(测试scanf 的返回值和num 的值)。您可以在您的情况下使用 sizeof 公式来避免对值进行硬编码,这仅仅是因为您有一个 array 指针,而不是指针上的指针。

还要避免转换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 运行您的代码,或者只执行分配/解除分配(而不是其余部分)以查找导致问题的代码部分。

【讨论】:

  • 我会放**temps,但你的建议更好
  • 感谢您的所有意见,非常感谢 Jean-Francois Fabre 的意见,谢谢兄弟。由于我的 num2 变量的性质,您还可以建议在 while 循环中填充数组时潜在的内存损坏的代码更正吗?
  • 请建议对潜在内存损坏 Jean 或 mnistic 的代码进行更正。谢谢你们,也谢谢大家
【解决方案2】:

释放动态分配的内存的正确方法是在检查它是否已被分配后释放它。由于分配和释放的循环结构相同,因此如果所有分配均成功,则此处不会有任何问题。所以我建议你在分配后检查所有地方是否分配成功,并在释放之前检查内存是否分配。

以下代码将确保所有情况:

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]时显然你已经越界了。

【讨论】:

    【解决方案3】:

    如果以下代码可以接受,请告诉我:

    #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);
    
    
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-30
      • 2015-06-19
      • 2013-04-18
      • 1970-01-01
      • 2011-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多