C 中的双重自由或腐败 3d 数组
double free or corruption 3d array in C
我在释放 3d 数组时遇到 'double free or corruption' 错误。谁能告诉我代码中的问题在哪里? 数组大小为2*N*N。这里 N 的值为 100。即使不转换,结果相同。
这是代码:
// Mallocing
double ***h = malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
h[i] = malloc(N * sizeof(double*));
for(j = 0; j < N; j++) {
h[i][j] = malloc(N * sizeof(double));
}
}
// Freeing
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++) {
free(h[i][j]);
}
free(h[i]);
}
free(h);
程序运行良好,但最后出现错误'double free or corruption (!prev): 0x08cd24f8'
已中止(核心已转储)。
问题在这里:
double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
// ...
}
你只有 malloc
2 个元素,并迭代 N
。
我猜你想拥有大小为 N*N*N
的数组,但你最终得到了 2*N*N
。
所以这个:
double ***h = (double***) malloc(2 * (sizeof(double**)));
应该是:
double ***h = (double***) malloc(N * (sizeof(double**)));
如果 N = 100
的值与您评论中的一样,那么您需要分配内存来保存 N 个指针到指针,而您只有 2 个。
double ***h = malloc(N * (sizeof(double*)));
不投malloc()
据我所知,您分配了 2 个项目,然后填充了 N 个项目。
double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
h[i] = (double**) malloc(N * sizeof(double*));
....
....
}
你正在覆盖未分配的 space 如果 N>2...
对于第一个维度,您分配了 2 个元素:
double ***h = (double***) malloc(2 * (sizeof(double**)));
但您将其视为具有 N
个元素:
for(i = 0; i < N; i++) {
h[i] = ...
将最外层循环比较分配 和 免费更改为:
for(i = 0; i < 2; i++) {
也不要投射 malloc
的 return 值。此外,您的代码缺少错误处理,如果分配失败就会中断。
正如其他人所指出的,导致错误的具体问题是您将具有 2 个元素的维度视为具有 N 个元素。
然而,造成这种情况的核心原因是混淆。我强烈建议您遵守一些规则:
始终将多维数组分配为在相邻内存中分配的真数组。 Reference.
切勿将多维数组分配为基于指针到指针的查找表,这些查找表在整个堆上都是零散的。它们不仅速度较慢并使代码更难阅读,而且它们实际上并不是数组。您不能将它们与 memcpy()
等一起使用
不幸的是,有无数糟糕的 C 编程老师和糟糕的书籍宣扬零散的指针到指针查找表。这么多程序员要忘掉这个,太可怕了...
切勿在程序中使用两级以上的间接寻址。永远不应该有这样做的理由,它所做的只是降低程序的可读性(参考 MISRA-C:2012 规则 18.5)。这实际上被称为“三星级节目”,这不是一个美化的词。
永远不要转换 malloc 的结果,因为 it is pointless to do so.
你应该做什么:
double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
...
free(array);
示例:
#include <stdio.h>
#include <stdlib.h>
#define X 2
#define Y 3
#define Z 4
int main (void)
{
double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
double count = 0.0;
for(int x=0; x<X; x++)
{
for(int y=0; y<Y; y++)
{
for(int z=0; z<Z; z++)
{
array[x][y][z] = count++;
printf("%f ", array[x][y][z]);
}
printf("\n");
}
printf("\n");
}
free(array);
return 0;
}
要编译这个,你需要一个不超过 16 岁的编译器。
我在释放 3d 数组时遇到 'double free or corruption' 错误。谁能告诉我代码中的问题在哪里? 数组大小为2*N*N。这里 N 的值为 100。即使不转换,结果相同。 这是代码:
// Mallocing
double ***h = malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
h[i] = malloc(N * sizeof(double*));
for(j = 0; j < N; j++) {
h[i][j] = malloc(N * sizeof(double));
}
}
// Freeing
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++) {
free(h[i][j]);
}
free(h[i]);
}
free(h);
程序运行良好,但最后出现错误'double free or corruption (!prev): 0x08cd24f8' 已中止(核心已转储)。
问题在这里:
double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
// ...
}
你只有 malloc
2 个元素,并迭代 N
。
我猜你想拥有大小为 N*N*N
的数组,但你最终得到了 2*N*N
。
所以这个:
double ***h = (double***) malloc(2 * (sizeof(double**)));
应该是:
double ***h = (double***) malloc(N * (sizeof(double**)));
如果 N = 100
的值与您评论中的一样,那么您需要分配内存来保存 N 个指针到指针,而您只有 2 个。
double ***h = malloc(N * (sizeof(double*)));
不投malloc()
据我所知,您分配了 2 个项目,然后填充了 N 个项目。
double ***h = (double***) malloc(2 * (sizeof(double**)));
for(i = 0; i < N; i++) {
h[i] = (double**) malloc(N * sizeof(double*));
....
....
}
你正在覆盖未分配的 space 如果 N>2...
对于第一个维度,您分配了 2 个元素:
double ***h = (double***) malloc(2 * (sizeof(double**)));
但您将其视为具有 N
个元素:
for(i = 0; i < N; i++) {
h[i] = ...
将最外层循环比较分配 和 免费更改为:
for(i = 0; i < 2; i++) {
也不要投射 malloc
的 return 值。此外,您的代码缺少错误处理,如果分配失败就会中断。
正如其他人所指出的,导致错误的具体问题是您将具有 2 个元素的维度视为具有 N 个元素。
然而,造成这种情况的核心原因是混淆。我强烈建议您遵守一些规则:
始终将多维数组分配为在相邻内存中分配的真数组。 Reference.
切勿将多维数组分配为基于指针到指针的查找表,这些查找表在整个堆上都是零散的。它们不仅速度较慢并使代码更难阅读,而且它们实际上并不是数组。您不能将它们与
memcpy()
等一起使用不幸的是,有无数糟糕的 C 编程老师和糟糕的书籍宣扬零散的指针到指针查找表。这么多程序员要忘掉这个,太可怕了...
切勿在程序中使用两级以上的间接寻址。永远不应该有这样做的理由,它所做的只是降低程序的可读性(参考 MISRA-C:2012 规则 18.5)。这实际上被称为“三星级节目”,这不是一个美化的词。
永远不要转换 malloc 的结果,因为 it is pointless to do so.
你应该做什么:
double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
...
free(array);
示例:
#include <stdio.h>
#include <stdlib.h>
#define X 2
#define Y 3
#define Z 4
int main (void)
{
double (*array)[Y][Z] = malloc( sizeof(double[X][Y][Z]) );
double count = 0.0;
for(int x=0; x<X; x++)
{
for(int y=0; y<Y; y++)
{
for(int z=0; z<Z; z++)
{
array[x][y][z] = count++;
printf("%f ", array[x][y][z]);
}
printf("\n");
}
printf("\n");
}
free(array);
return 0;
}
要编译这个,你需要一个不超过 16 岁的编译器。