1

假设我有一个用这样的东西创建的二维数组,

char **foo = (char **) malloc(height * sizeof(char *));
for(i = 0; i <= height; i++) 
    foo[i] = (char *) malloc (width * sizeof(char *));

首先,这甚至是创建这样一个数组的正确方法吗?这里的问题是,“高度”和“宽度”是在运行时设置的。

这似乎可行,但这是释放这个二维数组的最佳策略。免费(真菌)听起来不对。通过这里的其他一些帖子,我想我会一一释放每一行?

我确实尝试过这样的事情,

for (height = 0; height < ip_ptr->funge_height; height++) {
    free(funge[height]);
} 
free(funge)

然而,这给了我一个双自由指针异常。这是否意味着,我不必管理这块内存?我的印象是,对于每个 malloc 的内存,我们都应该调用 free()。

4

9 回答 9

8

由于所有“行”的大小相同,因此您可以一口气分配它malloc(height * width * sizeof (char *))(尚不清楚您是创建 2d 数组char还是 2d 数组char *)。您可以使用乘法来计算适当的索引(即foo[i][j]变为foo + i * height + j),

free()同样,它会接听一个电话。

于 2009-10-14T18:19:28.233 回答
8

在用于分配的 for 循环中,您使用i <= height;的是i < height;. 因此,您正在写入无效的内存位置,并且代码的行为变得不可预测。

于 2009-10-14T18:20:46.803 回答
7

第二个分配应该是:

foo[i] = (char *) malloc (width * sizeof(char));

您在height+1分配时也在循环时间。

除此之外,这两个片段对我来说似乎是正确的,所以错误应该在其他地方。

如果数组被分配为一大块内存,那么你只需要释放它一次。

char **foo = (char **) malloc(height * sizeof(char *));
*foo = malloc(height * width * sizeof(char))
for (int i = 1; i < height; i++) {
  foo[i] = *foo + i*width;
}
//and you just do 2 frees
free(*foo);
free(foo);
于 2009-10-14T18:22:36.017 回答
3

考虑到宽度和高度是运行时值,分配机制是可以的(尽管您应该在分配循环中使用sizeof(char)而不是sizeof(char *);您正在过度分配字符串)。

您应该为每个 malloc() 调用一次 free() 的印象基本上是正确的(像 calloc() 和 realloc() 这样的事情使简单的故事变得复杂)。

free 后面的循环应该是正确的(或者,至少是“首先释放子数组,然后是指向子数组的指针数组”的一般机制 - 所以你需要查看双重释放错误的来源. 我们看不到ip_ptr->funge_height被控制的地方;funge描述的不是很明显ip_ptr->funge_height


请参阅“unknown @ google”的答案 - 存在数组边界问题。

于 2009-10-14T18:19:50.593 回答
2

当你分配内存时,它应该i < height作为循环条件。

当您释放内存时,您应该迭代到与分配时相同的索引。 ip_ptr->funge_height应该和原来的一样height,但显然不是这样。

除此之外,它应该可以工作。

这是另一种方式,它涉及更少的 malloc 和 free。

分配:

char **foo = malloc (height * sizeof (char **));
foo[0] = malloc (height * width * sizeof (char *));
for (i = 1;  i < height;  ++i) {
    foo[i] = foo[i-1] + width;
}

解除分配:

free (foo[0]);
free (foo);
于 2009-10-14T18:21:48.663 回答
0

分配(假设高度 > 0 和宽度 > 0)

char **foo, *row;

assert(height > 0 && width > 0);
foo = malloc(height * sizeof *foo);
row = malloc(height * width * sizeof *row);
assert(foo != NULL && row != NULL);

for (i = 0; i < height; ++i, row += width) 
  foo[i] = row;

assert(row == *foo + height * width);

重新分配

assert(foo != NULL);
free(*foo);
free(foo);
于 2009-10-14T18:28:33.160 回答
0

在这种情况下,您始终可以使用 valgrind。只需编译您的可执行文件并运行它:

valgrind --leak-check=full ./a.out

Valgrind 将找到您所有的内存验证并指向所涉及的代码行。

在您的情况下,它可能很容易找到索引问题(< vs. <=)。

于 2009-10-14T18:33:49.857 回答
0

如果您的编译器支持它,您可以使用指向可变长度数组的指针,即

size_t width = 10, height = 5;
char *(*foo)[height][width] = malloc(sizeof *foo);

请记住,在访问数组元素之前,您必须取消对指针的引用,例如

(*foo)[1][2] = "foo";

这样做的好处是您将只分配一个连续的内存块,可以通过一次调用 fo 来释放它free()

于 2009-10-14T18:51:21.443 回答
0

这 100% 的作品没有 exe 崩溃。

char **map2d;
map2d=(char **)malloc(MAXY*sizeof(char *));
for(int a=0; a<MAXY; a++)
    map2d[a]=(char *)malloc(MAXX*sizeof(char));
for(int a=0; a<MAXX; a++)
    free(map2d[a]);
free(map2d);
于 2014-02-02T19:25:03.240 回答