英文:
Deallocating memory for array within a linked chain struct
问题
我正在尝试释放链接链中不同结构体使用的内存。dumpGroupingOrder()
函数应该释放所使用的内存,然而,一旦使用它,整个程序就停止运行。没有它,程序仍然工作,尽管存在内存泄漏,参见下面valgrind的输出:
LEAK SUMMARY:
definitely lost: 48 bytes in 1 blocks
indirectly lost: 328 bytes in 11 blocks
有了它,就没有内存泄漏,但我却得到一个 double free or corruption (out) 错误消息,并且从valgrind获得以下错误消息:
Invalid free() / delete / delete[] / realloc()
at 0x48399AB: free (vg_replace_malloc.c:538)
by 0x10929A: dumpGroupingOrder (code-stack.c:54)
by 0x10952F: main (code-stack.c:88)
Address 0x1fff0000b0 is on thread 1's stack
in frame #2, created by main (code-stack.c:74)
以下是用作MWE的整个代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct groupingOrder {
int *taxa;
size_t groupeSize;
long double distance;
struct groupingOrder* next;
};
void addGroup(struct groupingOrder* HEAD, int *groupe, size_t groupeSize, long double distance) {
struct groupingOrder* temp = HEAD;
// 移动最后一个单元结构
while(temp->next != NULL) {
temp = temp->next;
}
// 为单元结构分配空间
struct groupingOrder* nouveau = malloc(sizeof(struct groupingOrder));
nouveau->distance = distance;
nouveau->groupeSize = groupeSize;
// 为要存储的分类单元列表分配变量空间
nouveau->taxa = malloc(groupeSize * sizeof(int));
for(int i = 0; i < groupeSize; i++) {
nouveau->taxa[i] = groupe[i];
}
// 将新的单元结构链接到前一个单元结构
temp->next = nouveau;
// 指定NULL指针以标记最后一个单元
nouveau->next = NULL;
}
void dumpGroupingOrder(struct groupingOrder* HEAD) {
struct groupingOrder* temp = HEAD;
while(temp != NULL) {
// 复制当前单元的地址
struct groupingOrder* dumpTarget = temp;
// 在释放当前单元之前,存储下一个单元的地址
temp = temp->next;
// 释放当前单元及其分配的所有变量
if(dumpTarget->taxa != NULL) {
free(dumpTarget->taxa);
printf("#");
}
free(dumpTarget);
printf("* ");
}
}
void showGroupingOrder(struct groupingOrder* HEAD) {
struct groupingOrder* temp = HEAD;
while(temp->next != NULL) {
temp = temp->next;
for(int i = 0; i < temp->groupeSize; i++) {
printf(" %d", temp->taxa[i]);
}
printf(" %Lf\n", temp->distance);
}
}
int main() {
size_t groupeSize[6] = { 2,2,4,2,5,7 };
int groupes[][7] = { {2,3}, {5,1}, {2,3,5,1}, {7,4}, {2,3,5,1,6}, {2,3,5,1,6,7,4} };
struct groupingOrder HEAD = { .next = NULL };
for(int i = 0; i < 6; i++){
addGroup(&HEAD, groupes[i], groupeSize[i], 0.0003);
}
showGroupingOrder(&HEAD);
printf("\n\n");
dumpGroupingOrder(&HEAD);
return 0;
}
英文:
I am trying to deallocate the memory used by different struct that are part of a linked chain.
The dumpGroupingOrder() function is supposed to deallocate the memory used, however the whole program ceases to function once it is used. Without it the program works even though there are memory leaks, see the output of valgrind below:
LEAK SUMMARY:
definitely lost: 48 bytes in 1 blocks
indirectly lost: 328 bytes in 11 blocks
With it there are no memory leaks, but I get a double free or corruption (out) error message instead and the following error message from valgrind:
Invalid free() / delete / delete[] / realloc()
at 0x48399AB: free (vg_replace_malloc.c:538)
by 0x10929A: dumpGroupingOrder (code-stack.c:54)
by 0x10952F: main (code-stack.c:88)
Address 0x1fff0000b0 is on thread 1's stack
in frame #2, created by main (code-stack.c:74)
Below the entire code used as a MWE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct groupingOrder {
int *taxa;
size_t groupeSize;
long double distance;
struct groupingOrder* next;
};
void addGroup( struct groupingOrder* HEAD, int * groupe, size_t groupeSize, long double distance ) {
struct groupingOrder* temp = HEAD;
// Moving the last unit structure
while( temp->next != NULL ) {
temp = temp->next;
}
// Allocating space for the unit structure
struct groupingOrder* nouveau = malloc( sizeof( struct groupingOrder ) );
nouveau->distance = distance;
nouveau->groupeSize = groupeSize;
// Allocating variable space for the list of taxa to be stored
nouveau->taxa = malloc( groupeSize * sizeof( int ) );
for( int i = 0; i < groupeSize; i++) {
nouveau->taxa[i] = groupe[i];
}
// Linking the new unit structure to the previous one
temp->next = nouveau;
// Specifying the NULL pointer to label the last unit
nouveau->next = NULL;
}
void dumpGroupingOrder( struct groupingOrder* HEAD ) {
struct groupingOrder* temp = HEAD;
while( temp != NULL ) {
// Copying the address of the current unit
struct groupingOrder* dumpTarget = temp;
// Storing the address of the next unit before dumping the
// current one.
temp = temp->next;
// Dumping the current unit and all its allocated variables
if( dumpTarget->taxa != NULL ) {
free( dumpTarget->taxa );
printf( " #" );
}
free( dumpTarget );
printf( "* " );
}
}
void showGroupingOrder( struct groupingOrder* HEAD ) {
struct groupingOrder* temp = HEAD;
while( temp->next != NULL ) {
temp = temp->next;
for( int i = 0; i < temp->groupeSize; i++) {
printf( " %d", temp->taxa[i] );
}
printf( " %Lf\n", temp->distance );
}
}
int main() {
size_t groupeSize[6] = { 2,2,4,2,5,7 };
int groupes[][7] = { {2,3}, {5,1}, {2,3,5,1}, {7,4}, {2,3,5,1,6}, {2,3,5,1,6,7,4} };
struct groupingOrder HEAD = { .next = NULL };
for( int i = 0; i < 6; i++ ){
addGroup( &HEAD, groupes[i], groupeSize[i], 0.0003 );
}
showGroupingOrder( &HEAD );
printf( "\n\n" );
dumpGroupingOrder( &HEAD );
return 0;
}
答案1
得分: 2
Your function dumpGroupingOrder
tries to free everything in the list, including the HEAD
.
On the other hand, what is passed from the function main
as HEAD
is a pointer to a local variable, not a pointer returned from malloc()
family.
You mustn't free what are not NULL
nor things returned from malloc()
family.
You should change
struct groupingOrder* temp = HEAD;
in the function dumpGroupingOrder
to
struct groupingOrder* temp = HEAD->next;
to avoid freeing HEAD
.
英文:
Your function dumpGroupingOrder
tries to free everything in the list, including the HEAD
.
On the other hand, what is passed from the function main
as HEAD
is a pointer to a local variable, not a pointer returned from malloc()
family.
You mustn't free what are not NULL
nor things returned from malloc()
family.
You should change
struct groupingOrder* temp = HEAD;
in the function dumpGroupingOrder
to
struct groupingOrder* temp = HEAD->next;
to avoid freeing HEAD
.
答案2
得分: 2
如前面的回答中已经指出的,问题在于您的链表的头节点没有通过malloc
分配内存。因此,您不能调用free
释放该节点。
不过,与其他回答不同的是,我不建议在释放内存时跳过头节点来解决问题,而是建议重新构建您的程序,以使所有节点(包括头节点)都能平等对待,从而也为头节点分配内存使用malloc
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct groupingOrder {
int *taxa;
size_t groupeSize;
long double distance;
struct groupingOrder* next;
};
void addGroup(struct groupingOrder** HEAD, int* groupe, size_t groupeSize, long double distance) {
struct groupingOrder** temp = HEAD;
while (*temp != NULL) {
temp = &(*temp)->next;
}
struct groupingOrder* nouveau = malloc(sizeof(struct groupingOrder));
nouveau->distance = distance;
nouveau->groupeSize = groupeSize;
nouveau->taxa = malloc(groupeSize * sizeof(int));
for (int i = 0; i < groupeSize; i++) {
nouveau->taxa[i] = groupe[i];
}
nouveau->next = NULL;
*temp = nouveau;
}
void dumpGroupingOrder(struct groupingOrder** HEAD) {
struct groupingOrder* temp = *HEAD;
while (temp != NULL) {
struct groupingOrder* dumpTarget = temp;
temp = temp->next;
if (dumpTarget->taxa != NULL) {
free(dumpTarget->taxa);
printf(" #");
}
free(dumpTarget);
printf("* ");
}
*HEAD = NULL;
}
void showGroupingOrder(struct groupingOrder* HEAD) {
for (struct groupingOrder* temp = HEAD; temp != NULL; temp = temp->next) {
for (int i = 0; i < temp->groupeSize; i++) {
printf(" %d", temp->taxa[i]);
}
printf(" %Lf\n", temp->distance);
}
}
int main() {
size_t groupeSize[6] = {2, 2, 4, 2, 5, 7};
int groupes[][7] = {{2, 3}, {5, 1}, {2, 3, 5, 1}, {7, 4}, {2, 3, 5, 1, 6}, {2, 3, 5, 1, 6, 7, 4}};
struct groupingOrder* HEAD = NULL;
for (int i = 0; i < 6; i++) {
addGroup(&HEAD, groupes[i], groupeSize[i], 0.0003);
}
showGroupingOrder(HEAD);
printf("\n\n");
dumpGroupingOrder(&HEAD);
return 0;
}
这个程序的输出如下:
2 3 0.000300
5 1 0.000300
2 3 5 1 0.000300
7 4 0.000300
2 3 5 1 6 0.000300
2 3 5 1 6 7 4 0.000300
#* #* #* #* #* #*
英文:
As already pointed out in the other answer, the problem is that the head node of your linked list was not allocated by malloc
. Therefore, you are not allowed to call free
on that node.
However, in contrast to the other answer, I do not recommend that you fix the problem by leaving out the head node when freeing the memory, but rather to restructure your program so that all nodes (including the head node) are treated equally, so that also the memory for the head node gets allocated by malloc
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct groupingOrder {
int *taxa;
size_t groupeSize;
long double distance;
struct groupingOrder* next;
};
void addGroup( struct groupingOrder** HEAD, int * groupe, size_t groupeSize, long double distance ) {
struct groupingOrder** temp = HEAD;
// Make "temp" point to the "next" member of the last node of
// the list, or if the list is empty, make "temp" point to
// the pointer to the head node (which has the value NULL).
while( (*temp) != NULL ) {
temp = &(*temp)->next;
}
// Allocating space for the unit structure
struct groupingOrder* nouveau = malloc( sizeof( struct groupingOrder ) );
nouveau->distance = distance;
nouveau->groupeSize = groupeSize;
// Allocating variable space for the list of taxa to be stored
nouveau->taxa = malloc( groupeSize * sizeof( int ) );
for( int i = 0; i < groupeSize; i++) {
nouveau->taxa[i] = groupe[i];
}
// Specifying the NULL pointer to label the last unit
nouveau->next = NULL;
// Linking the new unit structure to the previous one
*temp = nouveau;
}
void dumpGroupingOrder( struct groupingOrder** HEAD ) {
struct groupingOrder* temp = *HEAD;
while( temp != NULL ) {
// Copying the address of the current unit
struct groupingOrder* dumpTarget = temp;
// Storing the address of the next unit before dumping the
// current one.
temp = temp->next;
// Dumping the current unit and all its allocated variables
if ( dumpTarget->taxa != NULL ) {
free( dumpTarget->taxa );
printf( " #" );
}
free( dumpTarget );
printf( "* " );
}
// Mark linked list as empty
*HEAD = NULL;
}
void showGroupingOrder( struct groupingOrder* HEAD ) {
for ( struct groupingOrder* temp = HEAD; temp != NULL; temp = temp->next ) {
for( int i = 0; i < temp->groupeSize; i++) {
printf( " %d", temp->taxa[i] );
}
printf( " %Lf\n", temp->distance );
}
}
int main() {
size_t groupeSize[6] = { 2,2,4,2,5,7 };
int groupes[][7] = { {2,3}, {5,1}, {2,3,5,1}, {7,4}, {2,3,5,1,6}, {2,3,5,1,6,7,4} };
struct groupingOrder *HEAD = NULL;
for ( int i = 0; i < 6; i++ ) {
addGroup( &HEAD, groupes[i], groupeSize[i], 0.0003 );
}
showGroupingOrder( HEAD );
printf( "\n\n" );
dumpGroupingOrder( &HEAD );
return 0;
}
It was necessary for me to modify the function main
and addGroup
. I also modified the other two functions, but these changes were not necessary.
This program has the following output:
2 3 0.000300
5 1 0.000300
2 3 5 1 0.000300
7 4 0.000300
2 3 5 1 6 0.000300
2 3 5 1 6 7 4 0.000300
#* #* #* #* #* #*
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论