请考虑我正在修改的这段代码,它读取文件并加载到双向链表中:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Node{
char * data;
struct Node *Next;
struct Node *Prev;
};
struct Doubly_Linked_List{
struct Node *headNode;
struct Node *tailNode;
int LLSize;
};
void InsertAtEnd(struct Doubly_Linked_List *myll, char* data );
void reBalance(struct Doubly_Linked_List *myll);
void PrintLL(struct Doubly_Linked_List *myll);
void append( struct Doubly_Linked_List *myll, char* data);
void PrintLL(struct Doubly_Linked_List *myll){
struct Node *Node = myll->headNode;
int i = 0;
while (Node){
//printf("Node is likely at %ld\n", Node->data);
printf("Index: %d has : %s", i, Node->data);
i++;
Node = Node->Next;
}
}
void reBalance(struct Doubly_Linked_List *myll){
printf("Rebalancing myll\n");
struct Node *Node = myll->headNode;
struct Node *LastNode;
int i = 0;
while (Node){
LastNode = Node;
i++;
Node = Node->Next;
}
myll->LLSize = i;
myll->tailNode = LastNode;
}
void append( struct Doubly_Linked_List *myll, char* data){
if (!myll->headNode){
printf("Inserting at start\n");
struct Node *NewHeadNode = malloc( sizeof(*NewHeadNode) ) ;
NewHeadNode->data = malloc( strlen(data) * sizeof(char) );
strcpy(NewHeadNode->data, data);
NewHeadNode->Prev = NULL;
NewHeadNode->Next = NULL;
myll->headNode = NewHeadNode;
} else {
printf("Inserting at end\n");
InsertAtEnd(myll, data);
}
}
void InsertAtEnd(struct Doubly_Linked_List *myll, char* data ){
//printf("%s was evoked\n", __func__);
reBalance(myll);
struct Node *Node = myll->tailNode;
struct Node *NewTailNode = malloc( sizeof(*NewTailNode) );
NewTailNode->data = malloc( strlen(data) *sizeof(char) );
strcpy(NewTailNode->data, data);
NewTailNode->Next = NULL;
NewTailNode->Prev = Node;
Node->Next = NewTailNode;
reBalance(myll);
}
void FreeMem(struct Doubly_Linked_List *myll){
//printf("%s was evoked\n", __func__);
reBalance(myll);
int i = 0;
struct Node *Node = myll->headNode;
while (Node){
struct Node *NextNode = Node->Next;
//printf("Freeing Node at Index: %d with data : %s\n", i, Node->data);
free(Node);
i++;
Node = NextNode;
}
free(myll);
}
int main(){
char *filename = "/proc/net/dev";
struct Doubly_Linked_List *myll = malloc(sizeof(myll));
FILE *fp = fopen(filename,"r");
if (!fp){
printf("Error!\n");
return 0;
}
char filetext[400];
while (fgets(filetext, 400, fp) ){
append(myll, filetext);
PrintLL(myll);
printf("myll->LLSize: %d\n", myll->LLSize);
}
fclose(fp);
FreeMem(myll);
return 0;
}
它工作正常,就像它枚举并打印链接列表一样,这看起来像它被要求读取的文件。
但是,valgrind 似乎表明我有内存泄漏:
==7755== 77 bytes in 1 blocks are definitely lost in loss record 1 of 2
==7755== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7755== by 0x1089FE: append (stack_overflow.c:53)
==7755== by 0x108BF7: main (stack_overflow.c:108)
==7755==
==7755== 494 bytes in 4 blocks are definitely lost in loss record 2 of 2
==7755== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7755== by 0x108AAF: InsertAtEnd (stack_overflow.c:70)
==7755== by 0x108A62: append (stack_overflow.c:60)
==7755== by 0x108BF7: main (stack_overflow.c:108)
==7755==
==7755== LEAK SUMMARY:
==7755== definitely lost: 571 bytes in 5 blocks
==7755== indirectly lost: 0 bytes in 0 blocks
==7755== possibly lost: 0 bytes in 0 blocks
==7755== still reachable: 0 bytes in 0 blocks
==7755== suppressed: 0 bytes in 0 blocks
==7755==
在烧了几个小时之后,它仍然在泄漏 - 571 字节是我能泄漏的最好的。我一定是在做一些我没有注意到的事情,并且想要另一双眼睛和指导。谢谢!
更新:1
谢谢!我根据回复和建议做了一些更改:切换到 calloc,并确保释放我从文件中读取的文本数据。
很高兴报告 valgrind 检查通过了:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Node{
char * data;
struct Node *Next;
struct Node *Prev;
};
struct Doubly_Linked_List{
struct Node *headNode;
struct Node *tailNode;
int LLSize;
};
void PrintLL(struct Doubly_Linked_List *myll);
void append( struct Doubly_Linked_List *myll, char* data);
void PrintLL(struct Doubly_Linked_List *myll){
//printf("%s was evoked\n", __func__);
struct Node *Node = myll->headNode;
int i = 0;
while (Node){
//printf("Node is likely at %ld\n", Node->data);
printf("Index: %d has : %s", i, Node->data);
i++;
Node = Node->Next;
}
printf("-----------------------------\n");
}
void Freemem(struct Doubly_Linked_List *myll){
struct Node *Node = myll->headNode;
while (Node){
struct Node *Next = Node->Next;
free(Node->data);
free(Node);
Node = Next;
}
free(myll);
}
void append( struct Doubly_Linked_List *myll, char* data){
if (!myll->LLSize){
printf("Inserting at start\n");
struct Node *NewHeadNode = calloc(5, sizeof(*NewHeadNode) ) ;
NewHeadNode->data = calloc( 1,( strlen(data) +2) );
strcpy(NewHeadNode->data, data);
myll->headNode = NewHeadNode;
myll->tailNode = NewHeadNode;
myll->LLSize = 1;
} else {
//printf("Inserting at end\n");
struct Node *OldTail = myll->tailNode;
struct Node *NewTailNode = calloc(1, sizeof(*NewTailNode) );
NewTailNode->data = calloc( 1,( strlen(data) +2) );
strcpy(NewTailNode->data, data);
// wire the pointers
OldTail->Next = NewTailNode;
NewTailNode->Prev = OldTail;
NewTailNode->Next = NULL;
// adjust our size
myll->LLSize++;
// set new tail node:
myll->tailNode = NewTailNode;;
}
}
int main(){
char *nic = "wlp4s0";
char *filename = "/proc/net/dev";
struct Doubly_Linked_List *myll = calloc(10,sizeof(myll));
FILE *fp = fopen(filename,"r");
if (!fp){
Freemem(myll);
perror("Error!\n");
return 1;
}
char filetext[400];
while (fgets(filetext, 400, fp) ){
append(myll, filetext);
PrintLL(myll);
printf("myll->LLSize: %d\n", myll->LLSize);
}
fclose(fp);
Freemem(myll);
return 0;
}
最佳答案
关于第一次泄漏。在函数 main()
中,在此代码块中:
if (!fp)
{
printf("Error!\n");
return 0;
}
此时代码执行中,对malloc()
的调用已经执行完毕,因此分配的内存需要传递给free()
作为替代方案,在以下语句之后才调用 malloc()
:
char filetext[400];
在函数:append()
中有一个检查:
if (!myll->headNode){
但是,当从 main()
调用时,数组 myll
尚未初始化为任何内容。第一个(未初始化)字段包含全部 0x00 的可能性很小。
您可能会尝试调用calloc()
,而不是第一次调用malloc()
(calloc将所有分配的内存设置为全部0x00)第一个结果是NO head条目始终使用有效数据生成
事情从那里开始走下坡路。
请更正
关于c - 将文件读取到双向链表时泄漏内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54385157/