动态2d数组的C结构:对象0x7FFEE94AB80的错误:未分配要释放的指针
我在macbook上使用的是clang-1000.11.45.5。我试图为动态分配的2D矩阵创建一个结构。看起来是这样的:动态2d数组的C结构:对象0x7FFEE94AB80的错误:未分配要释放的指针,c,memory,C,Memory,我在macbook上使用的是clang-1000.11.45.5。我试图为动态分配的2D矩阵创建一个结构。看起来是这样的: typedef struct { int m_rows; int m_cols; double **arr; double *data; } t_mtrx; t_mtrx *init_mtrx(int rows, int cols) { t_mtrx *A = malloc(sizeof(t_mtrx)); A ->
typedef struct
{
int m_rows;
int m_cols;
double **arr;
double *data;
} t_mtrx;
t_mtrx *init_mtrx(int rows, int cols)
{
t_mtrx *A = malloc(sizeof(t_mtrx));
A -> m_rows = rows;
A -> m_cols = cols;
A -> arr = malloc(rows * sizeof(*A->arr));
A -> data = malloc(rows * cols * sizeof(*A->data));
for(int i = 0; i < rows; i++, A -> data += cols)
A -> arr[i] = A -> data;
return A;
}
void del_mtrx(t_mtrx *A)
{
free(A->data);
free(A->arr);
}
当我运行这个程序时,除了del_mtrx
之外,其他一切都正常工作
$ ./a.out
[[ 1.00, 3223.00, 5.00],
[ 2.00, 0.00, -99.00],
[ 14.00, 134.00, 130.00]] 3 x 3
a.out(684,0x10533e5c0) malloc: *** error for object 0x7fea65c02a48: pointer being freed was not allocated
a.out(684,0x10533e5c0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
我知道问题在于
free(A->data)代码>因为当我注释它时没有错误,但我不确定如何释放它。当您从函数返回时,您的A->数据不再指向分配内存的开头。代码中有两个缺陷
for
循环正在更改A->data
的值。修改后的A->data
无法传递到free
,因为它不再指向内存块的开头
- 结构本身未被释放,导致内存泄漏。内存管理的一个简单规则是,每个
malloc
必须具有相应的空闲
解决第二个问题很容易,只需在del_mtrx
功能中使用free(A)
。第一个问题可以修复,如下面的代码所示。请注意,分配给A->arr
的地址相同,但A->data
未修改
t_mtrx *init_mtrx(int rows, int cols)
{
t_mtrx *A = malloc(sizeof(t_mtrx));
A->m_rows = rows;
A->m_cols = cols;
A->arr = malloc(rows * sizeof(*A->arr));
A->data = malloc(rows * cols * sizeof(*A->data));
for(int i = 0; i < rows; i++)
A->arr[i] = A->data + (i * cols);
return A;
}
void del_mtrx(t_mtrx *A)
{
free(A->data);
free(A->arr);
free(A);
}
A->data+=cols
-不要这样做。您将丢失存储在那里的地址的原始值,至少是从该指针丢失的。因此,free(A->data)
是一个未定义行为的配方。使用本地temp将该行指针向上移动到缓冲区。仅供参考,你用错了api。您正在严重泄漏内存t_mtrx*A=malloc(sizeof(t_mtrx))代码>这是内存泄漏,返回t\u mtrx
不是指向它的指针。让C为您复制结构。main
也必须更改,否则OP的代码将释放一个自动地址。调用init_matrx
后的deref是那里的死赠品(以及随后的del_mtrx
参数)。@user3386109同样,仅供参考,只需使用A->arr[i]=A->data+(i*cols)
将删除需要或偏移量
,并且仍然阻止修改A->数据
。只是换一种方式来解决同样的问题。这差不多涵盖了它。我使用main()
声明的数组中的自动地址作为定时炸弹,将OP的硬指针替换留在其托管结构中。@WhozCraig您100%错了,因为结构的内存是动态分配的,并且在函数返回后仍将保留。此内存的地址仅返回,并且100%正常。保持指针(或其作用域)的存在并不重要,因为只返回值。@P_uuj_uuu恕我直言,您不知道自己在说什么。在OP的代码中,在main()
中,您认为&A
指的是什么?在这个答案中,当它传递给del_mtrx
时,您认为会发生什么?具体地说,是该函数尾部的free(A)
?仅供参考,在内存管理方面,“100%错误”是多余的;要么是对的,要么是错的;部分学分不适用。根据刚刚发布的更改,此答案中的main
现在对于此答案中的del_mtrx
的实现是正确的。@WhozCraig感谢您的建议。i*cols
实现看起来确实更干净。
t_mtrx *init_mtrx(int rows, int cols)
{
t_mtrx *A = malloc(sizeof(t_mtrx));
A->m_rows = rows;
A->m_cols = cols;
A->arr = malloc(rows * sizeof(*A->arr));
A->data = malloc(rows * cols * sizeof(*A->data));
for(int i = 0; i < rows; i++)
A->arr[i] = A->data + (i * cols);
return A;
}
void del_mtrx(t_mtrx *A)
{
free(A->data);
free(A->arr);
free(A);
}
int main(void)
{
int rows = 3;
int cols = 3;
double ra[] = {1, 3223, 5},
rb[] = {2, 0, -99},
rc[] = {14, 134, 130};
t_mtrx *A = init_mtrx(rows, cols);
memcpy(A->arr[0], ra, sizeof(ra));
memcpy(A->arr[1], rb, sizeof(rb));
memcpy(A->arr[2], rc, sizeof(rc));
print_mtrx(A);
del_mtrx(A);
}