在malloc失败时如何释放二维数组

3

如果我有一个按如下方式分配的二维数组:

int** map;
map = malloc(number * sizeof(int*));
if(!(map)){
    printf("out of memory!\n");
    return 1;
}
for (int i = 0; i < number; i++){
    map[i] = malloc(number * sizeof(int));
    if (!(map[i])){
        printf("Not enough memory!\n");
        return 1;
    }
}

如果分配失败并进入if语句,我应该释放map和迄今为止分配的“columns”吗?如果是这样,我该如何操作?
目前我只是打印消息并返回1,但我不确定这是否是正确的方法。

你没有一个二维数组,那是一个基于指针的查找表。要分配一个二维数组,你必须使用 int (*map)[number] = malloc(sizeof (int[number][number])); 或等效的方法。区别在于,即一个二维数组的数据是在相邻的内存单元中分配的,这一点非常重要。 - Lundin
不要忘记检查外部 malloc 的返回值。 - user464502
@Lundin 哦,我不知道,除了数据分配方式不同之外,它们在使用方法/速度方面还有其他区别吗? - John Doe
@user464502 我忘记了,已经修复。谢谢 - John Doe
@JohnSmith 你所使用的方法唯一的优点是允许查找表的每个“维度”具有不同的大小,并在运行时更改大小。缺点是你的方法会导致堆分段、程序由于高速缓存失效而变得非常慢,代码也变得过于复杂,存在潜在的错误和内存泄漏风险。此外,实际分配时间也比你的代码慢得多。 - Lundin
3个回答

7

是的,你应该使用free(),否则会导致内存泄漏,如果这是一个长时间运行的程序,则可能会很重要。

使它更容易的一种方法是计算所有分配的总大小,并进行单个较大的malloc()而不是一堆较小的分配。这也可能(大大)更快,因为堆分配可能很昂贵。

这样,你只需要检查一次是否成功或失败,如果失败则无需任何free()

类似于这样:

int ** map_allocate(size_t number)
{
  int **base = malloc(number * sizeof (int *) + number * number * sizeof (int));
  if(base != NULL)
  {
    int *row = (int *) (base + number);
    for(size_t i = 0; i < number; ++i)
      base[i] = row + i * number;
  }
  return base;
}

我没有测试运行过这个,但类似的东西。

嗯,对于非常大且频繁访问的地图来说,使用这种方法是否仍然更快,还是在长期运行中可能变得更慢,因为我每次都需要计算我的数字所在的位置?如果它几乎总是更快,我可能会考虑使用类似你的解决方案(我需要尽量从程序的执行中缩短时间)。 - John Doe
@JohnSmith 什么?我并没有提出任何不同的数据结构,也没有什么“计算我的数字在哪里”的意思,我所提供的只是一种分配数组的替代方法。我很困惑。 - unwind

3

您可以使用:

if (!(map[i])){
    printf("Not enough memory!\n");

    while (--i>=0)
        free(map[i]);

    free(map);
    return 1;
}

1

在分配指针后立即将其设置为null。

int **map;

map = malloc(number * sizeof(int *));
if(!map)
    goto out_of_memory;
for(i=0;i<number;i++)
    map[i] = 0;

for(i=0;i<numbers;i++)
{
    map[i] = malloc(number * sizeof(int));
    if(!map[i])
        goto out_of_memory;
}

...

return 0;

out_of_memory:
    if(map)
        for(i=0;i<number;i++)
            free(map[i]);
    free(map);
    return -1;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接