C 中 free() 函数的问题和内存泄漏
Problem with free() function in C and memory-leaks
我有一个关于在 C 中使用 free() 释放内存的问题。
我的程序使用矩阵生成随机家谱树。根据家庭成员的数量,这个矩阵可能非常庞大。在我决定生成不止一棵树之前,该程序似乎运行良好。我注意到生成大约 100 棵树会导致我的 8GB RAM 被填满!我确定我可以编写更好的代码来减少内存需求,但我的问题仍然存在。
我使用 free() 来释放内存并且没有错误。我安装了 Valgrind 来查看发生了什么,它说每棵树肯定丢失了大约 1 亿字节。这意味着 free() 不能正常工作。我现在不知道问题出在哪里。我 link 一些我认为与问题相关的函数。
typedef struct{
int f_id;
char f_name[L_NAMES];
int generations;
int n_members;
type_people *members;
int_mtx *mtx;
}type_family;
上面的结构是给家庭的。
typedef struct temp{
int p_id;
char name[L_NAMES];
char f_name[L_NAMES];
int generation;
int n_sons;
struct temp **sons;
int f_id;
int sex;
int age;
}type_people;
这是给会员的。
typedef struct{
int i;
int j;
int **val;
}int_mtx;
和矩阵。
在主要我调用函数来初始化树:
type_family *family_a;
family_a = malloc(sizeof(type_family));
family_a = init_family_n_gen(family_a, 6);
这是 init_family_n_gen() 的第一部分:
type_family *init_family_n_gen(type_family *family, int n){
...
family->members = malloc(max_people * sizeof(type_people));
family->mtx = mtxcalloc(family->mtx, max_people, max_people - 1);
...
此代码用于初始化矩阵的 mtxcalloc:
int_mtx *mtxcalloc(int_mtx *mtx, int i, int j){
mtx = malloc(sizeof(int_mtx));
mtx->i = i;
mtx->j = j;
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
return mtx;
}
并结束解除分配家庭的代码:
void free_family(type_family *family){
for(int m = 0; m < family->n_members; m++){
if(family->members[m].n_sons != 0){
free(family->members[m].sons);
}
}
mtxfree(family->mtx);
free(family->members);
}
以及解除分配矩阵的那个:
void mtxfree(int_mtx *mtx){
for(int i = 0; i < mtx->i; i++){
free(mtx->val[i]);
}
free(mtx->val);
free(mtx);
}
Screen capture of Valgrind output
所以每次我需要重新生成家庭时我都会调用 free_family(family_a) 但内存仍然增加。 (在上面的照片中,如果我重新生成家庭 50 次,字节数将变为 10 亿)。
感谢支持!
已编辑
我做了一个最小的可复制示例来模拟我的原始代码。结构和变量是相同的,但我根据 Weather Vane 更改了函数:它们都是 void 并且我将双 ** 传递给它们。
init_family_n_gen 变为:
void init_family(type_family **f){
type_family *family = malloc(sizeof(type_family));
family->members = malloc(100 * sizeof(type_people));
for(int m = 0; m < 100; m++){
family->members[m].n_sons = 0;
}
mtxcalloc(&family->mtx, 100, 99);
family->mtx->val[0][1] = 7;
family->mtx->val[9][8] = 1;
mtxrealloc(&family->mtx, 5, 4);
*f = family;
}
主要是:
type_family *family_a;
init_family(&family_a);
free_family(&family_a);
我唯一添加的就是这个功能(代码对吗?):
void mtxrealloc(int_mtx **mtx, int i, int j){
(*mtx)->i = i;
(*mtx)->j = j;
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
for(int a = 0; a < (*mtx)->i; a++){
(*mtx)->val[a] = realloc((*mtx)->val[a], (*mtx)->j * sizeof(int));
}
}
我注意到当我使用 realloc 函数时会出现问题,但我不明白为什么。我 link 带有和不带有函数 mtxrealloc 的 Valgrind 图像。 (我看到还有一个 48 字节的泄漏......)。
Valgrind with realloc
Valgrind without realloc
再次感谢您的支持!
这个:
init_family(&family_a);
导致 mtxcalloc
中的代码执行:
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
,其中 i
,j
= 100, 99。也就是说,您为 100 个指针分配 space,并且为每个指针分配 space 99 int
秒。然后可以通过 family_a->mtx
.
访问这些内容
此后不久,您拨打了这个电话:
mtxrealloc(&family->mtx, 5, 4);
,其中包括:
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
丢失所有指针 (*mtx)->val[5]
到 (*mtx)->val[99]
,每个指针都是分配给 space 的唯一指针,足够 99 int
s 。总的来说,在您对正在准备的对象执行任何计算之前,足够 space 9405 int
s 已经泄漏。
目前还不清楚为什么要过度分配,只是为了立即(尝试)释放多余的部分,但这也许是代码简化的产物。最好想出一种方法来确定你提前需要多少 space,然后一开始只分配那么多。但是如果你确实需要重新分配这个特定的数据,那么你需要先释放每个将丢失的 (*mtx)->val[x]
。当然,如果您要重新分配更大的内存,那么您需要分配/重新分配 (*mtx)->val[x]
.
的 all
我有一个关于在 C 中使用 free() 释放内存的问题。 我的程序使用矩阵生成随机家谱树。根据家庭成员的数量,这个矩阵可能非常庞大。在我决定生成不止一棵树之前,该程序似乎运行良好。我注意到生成大约 100 棵树会导致我的 8GB RAM 被填满!我确定我可以编写更好的代码来减少内存需求,但我的问题仍然存在。 我使用 free() 来释放内存并且没有错误。我安装了 Valgrind 来查看发生了什么,它说每棵树肯定丢失了大约 1 亿字节。这意味着 free() 不能正常工作。我现在不知道问题出在哪里。我 link 一些我认为与问题相关的函数。
typedef struct{
int f_id;
char f_name[L_NAMES];
int generations;
int n_members;
type_people *members;
int_mtx *mtx;
}type_family;
上面的结构是给家庭的。
typedef struct temp{
int p_id;
char name[L_NAMES];
char f_name[L_NAMES];
int generation;
int n_sons;
struct temp **sons;
int f_id;
int sex;
int age;
}type_people;
这是给会员的。
typedef struct{
int i;
int j;
int **val;
}int_mtx;
和矩阵。 在主要我调用函数来初始化树:
type_family *family_a;
family_a = malloc(sizeof(type_family));
family_a = init_family_n_gen(family_a, 6);
这是 init_family_n_gen() 的第一部分:
type_family *init_family_n_gen(type_family *family, int n){
...
family->members = malloc(max_people * sizeof(type_people));
family->mtx = mtxcalloc(family->mtx, max_people, max_people - 1);
...
此代码用于初始化矩阵的 mtxcalloc:
int_mtx *mtxcalloc(int_mtx *mtx, int i, int j){
mtx = malloc(sizeof(int_mtx));
mtx->i = i;
mtx->j = j;
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
return mtx;
}
并结束解除分配家庭的代码:
void free_family(type_family *family){
for(int m = 0; m < family->n_members; m++){
if(family->members[m].n_sons != 0){
free(family->members[m].sons);
}
}
mtxfree(family->mtx);
free(family->members);
}
以及解除分配矩阵的那个:
void mtxfree(int_mtx *mtx){
for(int i = 0; i < mtx->i; i++){
free(mtx->val[i]);
}
free(mtx->val);
free(mtx);
}
Screen capture of Valgrind output 所以每次我需要重新生成家庭时我都会调用 free_family(family_a) 但内存仍然增加。 (在上面的照片中,如果我重新生成家庭 50 次,字节数将变为 10 亿)。 感谢支持!
已编辑
我做了一个最小的可复制示例来模拟我的原始代码。结构和变量是相同的,但我根据 Weather Vane 更改了函数:它们都是 void 并且我将双 ** 传递给它们。 init_family_n_gen 变为:
void init_family(type_family **f){
type_family *family = malloc(sizeof(type_family));
family->members = malloc(100 * sizeof(type_people));
for(int m = 0; m < 100; m++){
family->members[m].n_sons = 0;
}
mtxcalloc(&family->mtx, 100, 99);
family->mtx->val[0][1] = 7;
family->mtx->val[9][8] = 1;
mtxrealloc(&family->mtx, 5, 4);
*f = family;
}
主要是:
type_family *family_a;
init_family(&family_a);
free_family(&family_a);
我唯一添加的就是这个功能(代码对吗?):
void mtxrealloc(int_mtx **mtx, int i, int j){
(*mtx)->i = i;
(*mtx)->j = j;
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
for(int a = 0; a < (*mtx)->i; a++){
(*mtx)->val[a] = realloc((*mtx)->val[a], (*mtx)->j * sizeof(int));
}
}
我注意到当我使用 realloc 函数时会出现问题,但我不明白为什么。我 link 带有和不带有函数 mtxrealloc 的 Valgrind 图像。 (我看到还有一个 48 字节的泄漏......)。 Valgrind with realloc Valgrind without realloc 再次感谢您的支持!
这个:
init_family(&family_a);
导致 mtxcalloc
中的代码执行:
mtx->val = malloc(i * sizeof(int *)); for(int a = 0; a < i; a++){ mtx->val[a] = malloc(j * sizeof(int)); for(int b = 0; b < j; b++){ mtx->val[a][b] = 0; } }
,其中 i
,j
= 100, 99。也就是说,您为 100 个指针分配 space,并且为每个指针分配 space 99 int
秒。然后可以通过 family_a->mtx
.
此后不久,您拨打了这个电话:
mtxrealloc(&family->mtx, 5, 4);
,其中包括:
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
丢失所有指针 (*mtx)->val[5]
到 (*mtx)->val[99]
,每个指针都是分配给 space 的唯一指针,足够 99 int
s 。总的来说,在您对正在准备的对象执行任何计算之前,足够 space 9405 int
s 已经泄漏。
目前还不清楚为什么要过度分配,只是为了立即(尝试)释放多余的部分,但这也许是代码简化的产物。最好想出一种方法来确定你提前需要多少 space,然后一开始只分配那么多。但是如果你确实需要重新分配这个特定的数据,那么你需要先释放每个将丢失的 (*mtx)->val[x]
。当然,如果您要重新分配更大的内存,那么您需要分配/重新分配 (*mtx)->val[x]
.