C 会自动释放应用于函数的函数吗?

Does C automatically free functions applied to functions?

提问人:Ouilliam 提问时间:12/1/2021 更新时间:12/1/2021 访问量:120

问:

我正在使用 C 语言中的矩阵,并希望改进我的代码并确保没有内存泄漏。

我的矩阵实现如下所示:

typedef struct {
    int nb_cols;
    int nb_rows;
    float *data;
} matrix;

我有很多函数将两个矩阵作为输入,并返回一个输出。它们看起来像这样:

matrix *function(matrix* m1, matrix *m2)
{
    matrix* temp = matrix_init(m1->rows, m1->cols);

    // Doing some stuff 
    // like temp[i * (m1->cols) + j] = m1[ i * (m1->cols + j] + m2[i * (m2->cols + j];
    // (this is just an example)
    
    return temp;
}

当我像这样调用这些函数时:

mat = function1(function2(m1, m2), m3);

编译器是否自动允许临时矩阵,然后释放?或者我是否应该永远不要这样做,并拥有所有临时矩阵来逐个免费执行操作?

写这个更好吗?

mat_temp = function2(m1, m2);
mat = function1(mat_temp, m3);
free(mat_temp);

非常感谢您的回答!

C GCC 基质 Malloc Free

评论

1赞 mmixLinus 12/1/2021
您的建议更好,因为 malloc() 不知道它们的使用是多么“临时”
0赞 DannyNiu 12/1/2021
“将函数应用于函数的自由函数” 它可能应该是将输出从嵌套函数中解放出来。释放函数意味着解除分配与函数关联的代码段,这可能不是您的意思。

答:

1赞 chux - Reinstate Monica 12/1/2021 #1

第二更好。

在下面,返回的指针丢失,因此分配给它的内存缺少相应的 .内存泄漏function2()free()

// lost memory
mat = function1(function2(m1, m2), m3);

相反:

matrix *m1 = function0();
matrix *m2 = function0();
matrix *mat_temp = function2(m1, m2);
matrix *mat = function1(mat_temp, m3);
free(mat_temp);
...
free(mat);
free(m2);
free(m1);

旁白:

改进我的代码

如果指向的数据没有变化,请添加以允许更广泛的函数用法和一些优化。const

// matrix *function(matrix* m1, matrix *m2)
matrix *function(const matrix* m1, const matrix *m2)

如果调用代码不应提供重叠数据(没有意外的数据更改),请添加以让编译器应用更多优化。restrict

// matrix *function(matrix* m1, matrix *m2)
matrix *function(matrix* restrict m1, matrix * restrict m2)

...或两者兼而有之。constrestrict

好的代码还会测试失败的分配。

if (m == NULL) TBD_code();

评论

0赞 Ouilliam 12/1/2021
另一个问题:是否也会导致这些内存泄漏?就像回归自身并不能释放“以前存在”的东西一样,对吧?m1 = multiply(m1, m2);
0赞 chux - Reinstate Monica 12/1/2021
@Ouilliam是的。最好是 as 或编写另一个函数:并调用 as 并让它以最佳方式重新分配数据。matrix *t = multiply(m1, m2); free(m1); m1 = t;void multiply_equal(matrix** m1, const matrix* m2);multiply_equal(&m1, m2);m1
1赞 DannyNiu 12/1/2021 #2

编译器是否自动允许临时矩阵,然后释放?

不,编译器不会自动释放它们。

您可以在堆栈上分配一些矩阵数据(使用 C99 中的 VLA - 可变长度数组功能),但如果要将其传递给其他子例程,则必须使用堆(malloc、calloc、realloc 和 free,以及其他一些特定于平台的子例程)

或者我不应该这样做,并使用临时矩阵一个接一个地处理操作,然后释放临时矩阵

如果您不熟悉内存管理,并且愿意为了正确性而牺牲效率,那么无拷贝分配并不是一个坏策略。

但是,请放心,因为我已经有一段时间没有使用内存管理进行编程了。

在我最近的个人项目中,我一直在做的是,我静态地分配所有变量,首先估计最大必要的内存,然后分配,并且在程序的整个生命周期中从不释放任何工作上下文。