我有一个temp_line
内存泄漏的问题。
这个函数从文件中读取整个文本,并将每个单词分配给一个大链表。当我退出这个函数时,我无法找出谁是temp_line
的所有者,每当我试图用非动态变量(如temp_line[1000]
)替换temp_line
时,每次我得到一个新行,它都会覆盖旧行的数据(然后我得到一个分段错误)。
所以我真的不知道如何解决它。
int fill(FILE *f, LinkedList *linkedlist) {
FILE *file = fopen((const char *)f, "r");
char line[MAX_LINE]; //MAX_LINE = 1000
while (fgets(line, MAX_LINE, file) != NULL) {
char *temp_line = malloc(MAX_LINE);
if (temp_line == NULL) {
fclose(file);
return false;
}
strcpy(temp_line, line);
read_line(linkedlist, temp_line);
}
fclose(file);
return true;
}
int read_line(LinkedList *linkedlist, char *line) {
char *word;
while (true) {
word = strtok(NULL, "n ");
if (word == NULL) {
break;
}
add_node(linkedlist, word);
}
return true;
}
add_node
将节点添加到链表中并返回该节点。
代码中存在多个问题:
-
FILE *file = fopen((const char *)f, "r");
与f
定义为FILE *f
可能不正确。如果你有一个FILE *
,直接从上面读。 -
strtok
应该先用字符串调用,然后用NULL
调用,直到返回NULL
。 -
将节点从指针插入到
read_line
分配的块的中间。没有办法确定这样一个块的开始,也没有办法确定有多少指针指向块。以这种方式分配和使用的内存不能被释放。您应该使用strdup()
来分配单词的各个副本。这些指针可以稍后使用del_node()
函数中的free()
释放。或者,add_node()
可以复制string参数,这与del_node()
释放该数据是一致的。 -
关于你的问题:无法找到谁是malloc块的所有者…实际上,跟踪已分配的内存是C程序员的责任。无法测试指针是否有效,也无法测试它是否指向已分配的块。您必须始终如一地设计程序,以便始终可以根据上下文确定内存所有权。
下面是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int read_line(LinkedList *linkedlist, char *line) {
char *word;
while ((word = strtok(line, "n ")) != NULL) {
add_node(linkedlist, strdup(word));
line = NULL;
}
return true;
}
int fill(FILE *file, LinkedList *linkedlist) {
char line[MAX_LINE];
while (fgets(line, sizeof line, file) != NULL) {
read_line(linkedlist, line);
}
return true;
}
我正在尝试用非动态变量(如temp_line[1000])替换temp_line
temp_line[1000]
又称"自动记忆";因为它在其作用域结束时被自动释放。这意味着temp_line
将在每次循环迭代时被释放。
strtok
不分配任何内存。word
指向temp_line
内部的内存。
让我们假设你做了。
while (fgets (line, MAX_LINE, file) != NULL) {
char temp_line[MAX_LINE];
strcpy(temp_line, line);
read_line(linkedlist, temp_line);
}
在每个循环中,temp_line
将被分配,传递给read_line
,然后被释放。添加到链表中的单词指向已释放的内存。
问题是谁"拥有"?内存。因为它使用strtok
,所以read_line
假定它拥有line
,并且line
不会被释放。安全的做法是更改read_line
,使其从line
中复制每个word
。
int read_line(LinkedList *linkedlist, char *line) {
for(
char *word = strtok(line, "n ");
word;
word = strtok(NULL, "n ")
) {
// Duplicate the word so it no longer refers to line.
add_node(linkedlist, strdup(word));
}
return true;
}