提问人:Ouilliam 提问时间:12/1/2021 更新时间:12/1/2021 访问量:120
C 会自动释放应用于函数的函数吗?
Does C automatically free functions applied to functions?
问:
我正在使用 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);
非常感谢您的回答!
答:
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)
...或两者兼而有之。const
restrict
好的代码还会测试失败的分配。
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,以及其他一些特定于平台的子例程)
或者我不应该这样做,并使用临时矩阵一个接一个地处理操作,然后释放临时矩阵
如果您不熟悉内存管理,并且愿意为了正确性而牺牲效率,那么无拷贝分配并不是一个坏策略。
但是,请放心,因为我已经有一段时间没有使用内存管理进行编程了。
在我最近的个人项目中,我一直在做的是,我静态地分配所有变量,首先估计最大必要的内存,然后分配,并且在程序的整个生命周期中从不释放任何工作上下文。
评论