Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
动态2d数组的C结构:对象0x7FFEE94AB80的错误:未分配要释放的指针_C_Memory - Fatal编程技术网

动态2d数组的C结构:对象0x7FFEE94AB80的错误:未分配要释放的指针

动态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 ->

我在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 -> 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);
}