如何解决块内的内存泄漏?
How to solve this memory leak inside a block?
我有以下功能:
STUDENT *getStudents(size_t *numOfStudents){
STUDENT *students=malloc(sizeof(STUDENT));
if(students==NULL){
fprintf(stderr,"Could not allocate memory. Aborting...\n");
exit(-1);
}
FILE *data=fopen("in/data.txt","r");
for(register size_t i=0;fscanf(data,"%"SCNd32" %"SCNd8,&students[i].num,&students[i].finalGrade)==2;i++){
++(*numOfStudents);
{
STUDENT *sTemp=realloc(students,*numOfStudents*sizeof(STUDENT));
if(sTemp==NULL){
fprintf(stderr,"Could not allocate memory. Aborting...\n");
exit(-1);
}
students=sTemp;
}
}
--(*numOfStudents);
{
STUDENT *sTemp=realloc(students,*numOfStudents*sizeof(STUDENT));
if(sTemp==NULL){
fprintf(stderr,"Could not allocate memory. Aborting...\n");
exit(-1);
}
students=sTemp;
}
return students;
}
使用 -fsanitize=address
编译,它检测到内存泄漏
in getStudents src/student.c:27
也就是下面一行:
STUDENT *sTemp=realloc(students,*numOfStudents*sizeof(STUDENT));
我以为它会自动释放内存,因为它在一个块中。即使在尝试释放它之后,还是会出现同样的问题。
我该如何解决这个问题?
编辑:
int main(void){
size_t numOfStudents=1;
STUDENT *students=getStudents(&numOfStudents);
printStudents(students,numOfStudents);
printf("\n================\nMean: %f\n================\n\n",
(float)getGradeSum(students,numOfStudents)/numOfStudents
);
students=removeFailed(students,&numOfStudents);
printStudents(students,numOfStudents);
getGradeSum(students,numOfStudents);
free(students);
return 0;
}
int32_t getGradeSum(STUDENT *students,size_t numOfStudents){
if(numOfStudents==1){
return students[0].finalGrade;
}
else{
return students[numOfStudents-1].finalGrade+getGradeSum(students,numOfStudents-1);
}
}
如果 students
指向的内存被自动释放(但不是因为 C 中没有这样的东西),那么你将无法 return students
因为你将是 return 悬挂指针。
您的函数所做的是动态分配一个正确大小的数组并将其 return 分配给调用者。这使得调用者有责任调用 free()
.
Valgrind 只是告诉你 free()
从未在该内存上调用过。
现在您的程序有更多(但不是全部)可用,我猜罪魁祸首实际上是这一行:
students=removeFailed(students,&numOfStudents);
据推测,removeFailed
returns 是一个与给定的指针不同的指针,因为它复制了正在传递的数组(的一部分)。由于它不会释放作为参数传递的指针,因此该分配仍然存在。但是,由于您已将 students
(在 main
中)的值替换为数组副本的地址,因此您无法再从 main
中释放该内存。所以这肯定是内存泄漏。
我有以下功能:
STUDENT *getStudents(size_t *numOfStudents){
STUDENT *students=malloc(sizeof(STUDENT));
if(students==NULL){
fprintf(stderr,"Could not allocate memory. Aborting...\n");
exit(-1);
}
FILE *data=fopen("in/data.txt","r");
for(register size_t i=0;fscanf(data,"%"SCNd32" %"SCNd8,&students[i].num,&students[i].finalGrade)==2;i++){
++(*numOfStudents);
{
STUDENT *sTemp=realloc(students,*numOfStudents*sizeof(STUDENT));
if(sTemp==NULL){
fprintf(stderr,"Could not allocate memory. Aborting...\n");
exit(-1);
}
students=sTemp;
}
}
--(*numOfStudents);
{
STUDENT *sTemp=realloc(students,*numOfStudents*sizeof(STUDENT));
if(sTemp==NULL){
fprintf(stderr,"Could not allocate memory. Aborting...\n");
exit(-1);
}
students=sTemp;
}
return students;
}
使用 -fsanitize=address
编译,它检测到内存泄漏
in getStudents src/student.c:27
也就是下面一行:
STUDENT *sTemp=realloc(students,*numOfStudents*sizeof(STUDENT));
我以为它会自动释放内存,因为它在一个块中。即使在尝试释放它之后,还是会出现同样的问题。
我该如何解决这个问题?
编辑:
int main(void){
size_t numOfStudents=1;
STUDENT *students=getStudents(&numOfStudents);
printStudents(students,numOfStudents);
printf("\n================\nMean: %f\n================\n\n",
(float)getGradeSum(students,numOfStudents)/numOfStudents
);
students=removeFailed(students,&numOfStudents);
printStudents(students,numOfStudents);
getGradeSum(students,numOfStudents);
free(students);
return 0;
}
int32_t getGradeSum(STUDENT *students,size_t numOfStudents){
if(numOfStudents==1){
return students[0].finalGrade;
}
else{
return students[numOfStudents-1].finalGrade+getGradeSum(students,numOfStudents-1);
}
}
如果 students
指向的内存被自动释放(但不是因为 C 中没有这样的东西),那么你将无法 return students
因为你将是 return 悬挂指针。
您的函数所做的是动态分配一个正确大小的数组并将其 return 分配给调用者。这使得调用者有责任调用 free()
.
Valgrind 只是告诉你 free()
从未在该内存上调用过。
现在您的程序有更多(但不是全部)可用,我猜罪魁祸首实际上是这一行:
students=removeFailed(students,&numOfStudents);
据推测,removeFailed
returns 是一个与给定的指针不同的指针,因为它复制了正在传递的数组(的一部分)。由于它不会释放作为参数传递的指针,因此该分配仍然存在。但是,由于您已将 students
(在 main
中)的值替换为数组副本的地址,因此您无法再从 main
中释放该内存。所以这肯定是内存泄漏。