C 使用方法链接时释放指针的正确方法

C 使用方法链接时释放指针的正确方法,c,memory-management,free,C,Memory Management,Free,我目前正在用c编写多个不同的矩阵乘法实现。因此,我编写了矩阵加减的实用函数,其结构如下: int** m_sub(int** a, int** b, int size) { int **result = get_matrix(size); // calculate addition of a & b return result; } 使用get_matrix(): 我知道我可以通过将每个返回的int**分配给一个变量,然后手动释放它来解决这个问题。然而,这将导致

我目前正在用c编写多个不同的矩阵乘法实现。因此,我编写了矩阵加减的实用函数,其结构如下:

int** m_sub(int** a, int** b, int size) {
    int **result = get_matrix(size);
    // calculate addition of a & b
    return result;
}

使用
get_matrix():

我知道我可以通过将每个返回的
int**
分配给一个变量,然后手动释放它来解决这个问题。然而,这将导致大量临时分配的变量,从而(可以说)减少代码的可读性


现在我想知道在c中是否有一种“正确”的方法来实现这一点?或者我返回的是“代码> int *>代码>指针,这些矩阵已经是一个坏的设计选择?

< p>问题是C没有自动析构函数调用的概念,如C++一样。好吧,作为程序员,你有责任释放任何分配的东西

当然,您可以想象这样一个库,它保存它所分配的任何内容的引用,并在您不再需要它时提供一种释放这些内容的方法。例如,您可以实现一个动态堆栈来存储每个新分配的内存块,并在以后使用该堆栈回收整个内存


只是我太懒了,无法编写它的实现。。。但是,如果你觉得你想这样做,但不能从一开始就实现它,请随意在评论中ping我。

实际上,在C中手动释放每个指针是正确的方法,因为正如Serge所写的,C中没有自动析构函数调用。但是,你可以在不使用动态堆栈或垃圾堆的情况下,使其手动且漂亮收藏家式的解决方案,在我看来,这通常是一个巨大的过度杀伤力。所以不用再麻烦了

  • 命名creator函数,以便它可以像create一样分配内存。。。或分配。。。或者新的。。。而不是得到。让我们假设在这里创建/删除术语。因此:

    int*创建_矩阵(int大小)

  • 注意我使用的是
    int*
    ,而不是
    int**
    。它更方便,不需要您进行所有的二维分配,您只需分配一个大小为
    n*n
    的数组即可。在内存中,这是相同的空间。但是,如果愿意,您可以坚持使用二维

  • 接下来是析构函数

    void delete_矩阵(int*matrix)

  • 现在我们有了一些漂亮的语法,我们修改了您的操作原型。操作第一个参数,而不是获取两个数组并返回一个新分配的数组。分配数据的乘法函数不好,因为假定乘法分配新数据而不是按值返回数据是不直观的。因此:

    int*matmul\u递归(int*left,const int*right,int size)

  • 注意:我们不会修改
    右侧
    ,因此常量为。我们将修改
    左侧
    ,因此没有常量。现在将
    left
    right
    的乘法写入
    left
    。没有额外分配意味着没有泄漏。函数应该返回
    left
    ,以方便链式调用

    注意,您可以添加一个
    int*create\u matrix\u copy(const int*source,int size)以克隆矩阵

    还要注意的是,在操作之后,通常不需要操作的参数。您将对生成的累积矩阵感兴趣。请参见此示例(使用函数名):

    如果适用,也可以使用
    const
    ,即不更改参数的值,以避免错误。也可以考虑使用<代码>无符号int >代码>大小。

    通常情况下,您可能会在一个矩阵上执行许多操作,因此这将更常见(如3D变换):


    C
    中,您没有
    C++
    中所拥有的奢侈品,因此内存分配只留给您。如果您确实希望避免逐个取消分配矩阵,可以执行以下操作:

    创建一个
    struct
    ,负责存储所创建矩阵的所有地址(我们称之为容器)

  • 因此,您的函数还将获取指向该矩阵容器对象的指针。当调用get_矩阵时,新分配的矩阵的地址被添加到容器中

  • 在计算结束时,您需要做的就是正确地释放容器

  • 类似于以下内容(下面的伪代码):

    destroy_container
    在矩阵向量上循环并逐个释放它们


    请不要认为注释
    get_matrix
    中所述的有问题<代码>整数**m=malloc(大小*大小(整数))应该是
    int**m=malloc(size*sizeof(int*)
    因为您需要为指针分配空间,而不是为
    int
    s分配空间。

    您不能反过来做吗?在循环中释放
    m[i]
    指针,最后释放
    **m
    ?(@Inian的意思是
    free(m[i]);
    在循环中,然后
    free(m);
    )是的,我知道如何通过循环释放从
    get_matrix()
    获得的矩阵。问题更多的是“即使我不将返回的
    int**
    赋值给变量,但直接将其用作另一个函数的参数,我是否可以释放它们?”
    int**m=malloc(size*sizeof(int))
    非常错误,它假定指针的大小是整数的大小。它应该是
    int**m=malloc(size*sizeof*m)
    ,即
    sizeof(int*)
    ,但没有重复类型,并且对所讨论的变量有一点“锁定”。我一直在考虑类似的事情。所以你会建议在计算中使用某种“全局”堆栈,并将所有临时变量推到上面,对吗?没错。它可以是编译单元中的静态成员,其中包含分配和解除分配的例程-注意,不要忘记显式初始化i
    int** get_matrix(int size){
        int** m = malloc(size*sizeof(int));
        for (int i=0;i<size;i++){
            m[i] = malloc(size*sizeof(int));
        }
        return m;
    
    m_copy(c_11,m_add(matmul_recursive(n/2, a,e),matmul_recursive(n/2, b, g), n/2), n/2);
    
    int* arg1 = create_matrix(n);
    int* arg2 = create_matrix(n);
    int* product1 = create_matrix(n);
    int* product2 = create_matrix(n);
    int* result = m_add(matmul_recursive(product1, arg1, n), matmul_recursive(product2, arg2, n), n);
    delete_matrix(arg1);
    delete_matrix(arg2);
    delete_matrix(product2);
    printf("%d", product1[0]);
    printf("%d", result[0]); // result == product1
    delete_matrix(product1);
    
    int* result = create_matrix(n);
    int* rotate = create_matrix(n);
    int* translate = create_matrix(n);
    int* scale = create_matrix(n);
    matmul_recursive(matmul_recursive(matmul_recursive(result, rotate, n), translate, n), scale, n);
    printf("%d", result[0]);
    // Remember to delete all arguments.
    
    int** get_matrix(int size, struct MatricesContainer* cnt){ //takes the container
        int** m = malloc(size*sizeof(int));
        for (int i=0;i<size;i++){
            m[i] = malloc(size*sizeof(int));
        }
        vector_push_back(m, cnt); //push_the address in the container
        return m;
    }
    
    int** m_sub(int** a, int** b, int size, struct MatricesContainer* cnt) {
        int **result = get_matrix(size, cnt); //address of result is stored in cnt
        // calculate addition of a & b
        return result;
    }
    
    int heavy_calculation(...)
    {
    struct MatricesContainer* cnt
       .....
       m_copy(c_11,m_add(matmul_recursive(n/2, a,e, cnt),matmul_recursive(n/2, b, g,cnt),   n/2), n/2,cnt); 
       ...
       destroy_container(cnt);
    }