找不到内存泄漏的所有者



我有一个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;
}

最新更新