请考虑一下我正在修改的这段代码,它会读取文件并将其加载到双向链接列表中:
#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;
}
答案 0 :(得分:1)
关于第一次泄漏。在函数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),第一个结果是永远不会生成带有有效数据的头条目
事情从那里走下坡路。
请更正