【问题标题】:Memory leaking in C, malloc inside functionC中的内存泄漏,函数内部的malloc
【发布时间】:2017-04-06 10:26:02
【问题描述】:

我正在尝试创建 struct grid_t 的二维数组,并通过地址清理程序收到内存泄漏警告,并最终在某些情况下出现段错误。

我的代码中可能有多个点导致了这种情况,但我认为知道这里出了什么问题会为我指明正确的方向来修复其余部分。

我是 C 和内存管理的新手,因此欢迎和感谢所有反馈!

void createGridArray(atom_t* ATOM) {
  ATOM -> grid = (grid_t**) malloc(WIDTH * sizeof(grid_t*));

  grid_t *nullGrid = malloc(sizeof(grid_t));
  grid_t temp = {NULL, 0};
  *nullGrid = temp;


  for (int i = 0; i < WIDTH; i++) {
    (ATOM -> grid)[i] = malloc(HEIGHT * sizeof(grid_t));
    for (int j = 0; j < HEIGHT; j++) {
        (ATOM -> grid)[i][j] = *nullGrid;
    }
  }
  //free(nullGrid); <- do I do this now?
  return;
}

【问题讨论】:

标签: c memory-leaks malloc


【解决方案1】:

首先,不要从malloc() 中投射返回值。在 C 中它不是必需的,并且可以掩盖严重的错误。

其次,不要将类型硬编码到malloc() 调用中。例如,

ATOM->grid = (grid_t**) malloc(WIDTH * sizeof(grid_t*));

将被替换为

ATOM->grid = malloc(WIDTH * sizeof(*(ATOM->grid)));

这确保分配的内存具有所需的大小,无论ATOM-&gt;grid 是指向什么的指针。

要回答您的问题,要释放所有内存,您需要将malloc() 返回的每个非NULL 指针传递给free()。正好一次。

所以,如果你这样分配

ATOM->grid = malloc(WIDTH * sizeof(*(ATOM->grid)));

grid_t *nullGrid = malloc(sizeof(*nullGrid));
grid_t temp = {NULL, 0};
*nullGrid = temp;

for (int i = 0; i < WIDTH; i++)
{
    (ATOM -> grid)[i] = malloc(HEIGHT * sizeof(*((ATOM->grid)[i])));
    for (int j = 0; j < HEIGHT; j++) {
        (ATOM -> grid)[i][j] = *nullGrid;
}

解除分配的一种方式是

for (int i = 0; i < WIDTH; i++)
{
    free((ATOM -> grid)[i]);
}
free(ATOM->grid);
free(nullGrid);

在这种情况下,您不能在任何free((ATOM -&gt; grid)[i]) 之前安全地使用free(ATOM-&gt;grid)(除非您将所有(ATOM-&gt;grid)[i] 存储在其他地方,这有点不合时宜)。个人(ATOM-&gt;grid)[i] 可以按任何顺序被释放(只要每个都只释放一次)。

最后,检查malloc() 返回的指针。它在失败时返回 NULL,并且取消引用 NULL 指针会产生未定义的行为。

【讨论】:

  • 为什么不简单地(ATOM -&gt; grid)[i] = calloc(HEIGHT, sizeof(*((ATOM-&gt;grid)[i])));?现在不再需要将其设置为零的循环(所有问题都消失了)。
  • OP 使用malloc() 并以这种方式初始化,而不是我。所以我简单地解释了如何清理。我的建议实际上是关于防止错误。在 OP 的设置方式上还有很多其他可能的改进——使用 calloc() 只是其中之一——但问题不在于那个。
  • 谢谢。移除了演员表,使用了 calloc,经过一番摆弄后,有了一些工作代码
【解决方案2】:

是的,您需要在此处free(nullGrid); 以避免内存泄漏。

但实际上您可以将代码简化为:

void createGridArray(atom_t* ATOM) {
  ATOM -> grid = (grid_t**) malloc(WIDTH * sizeof(grid_t*));

  grid_t nullGrid = {NULL, 0};

  for (int i = 0; i < WIDTH; i++) {
    (ATOM -> grid)[i] = malloc(HEIGHT * sizeof(grid_t));
    for (int j = 0; j < HEIGHT; j++) {
        (ATOM -> grid)[i][j] = nullGrid;
    }
  }
}

这里根本需要mallocing nullGrid。顺便说一句,void 函数末尾的 return 是隐式的。

你也不会这样做:

void Foo()
{
   ...
   int *temp = malloc(sizeof(int));
   *temp = ...;
   ...
      bar = *temp;

   ...
   free(temp);
}

而是:

void Foo()
{
   ...
   int temp
   temp = ...;
   ...
      bar = temp;

   ...
}

【讨论】:

    【解决方案3】:

    当您将其视为“贷款”时,C 内存分配更容易。

    不知何故,当你调用 malloc() 时系统会借给你一些内存,你必须用 free() 把它还给它。

    【讨论】:

      猜你喜欢
      • 2020-05-26
      • 2019-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多