内存泄漏:从文件中读取并返回行

Memory Leak: Reading and returning line from file

我正在尝试从文件中读取一行 return 该行。但是,我不断遇到内存泄漏,丢失了 4000 个字节,并且比 allocs 少了一个字节。我不知道为什么会这样。下面是函数。

char *readLine(FILE *input, int lineNum) {

    char *string = calloc(MAX_LEN, sizeof(char));
    rewind(input);
    char *check = fgets(string, MAX_LEN, input);

    int stringLength = strlen(string);

    if (stringLength > MAX_LEN) {
        printf("Line too long to stdout.");
        free(string);
        return EXIT_SUCCESS;
    } else
    if (check == NULL) {
        free(string);
        return NULL;
    }
    return string;
}

我是这样称呼它的:

char *line = readLine(input, 0);

注意:忽略lineNum的东西,我会在解决内存泄漏后加入。

那么,内存泄漏的原因和位置在哪里?详尽的解释将非常有帮助。谢谢大家!

编辑: 这是调用 readLine() 的函数:

char *makeSummary(FILE *input, int summaryNum) {
   char *line = readLine(input, 0); //Get first line
   int lineLength = strlen(line);

    if (summaryNum == 1) {
        //Get the last line of file by looping till NULL
        lineNum = 10; 

        line = readLine(input, lineNum);
        //Do more stuff with line
   }
   free(line);
}

您的函数在需要 return 时不会 free(string)(这是有道理的),因此除非您未发布的部分代码是 free-查看它(由于显而易见的原因,这里的任何人都无法分辨),这就是你的漏洞。

谢谢大家,特别是@WhozCraig。问题在于使用 readLine 的函数在实际读取所需的行号之前没有释放 Line。现在已修复此问题,一切正常。

您的代码存在一些问题:

  • 在函数 readLine 中,您在测试 check == NULL 之前计算 string 的长度。这可能是不正确的。

  • 另外,string的长度根据定义小于MAX_LEN,你测试总是假的。您可能需要检查该行是否以换行符结尾以检测截断。

  • 你returnEXIT_SUCCESS,但是函数return是char *。编译器不会检测到这种差异,因为 EXIT_SUCCESS 定义为 0,因此 return EXIT_SUCCESS;return NULL;.

  • 相同
  • 在函数 makeSummary 中,您似乎用指针 return 覆盖了 line 并在下一次调用 readLine() 时被修改。您必须line = readLine(input, 0)之前调用free(line);

  • 你在readLine()中调用了rewind(),所以你一直从输入文件中读取同一行,除非文件不能被查找(比如终端),如果你正在从一个普通文件中读取,你永远不会读完。

这是分配更少字节的修改版本:

char *readLine(FILE *input, int lineNum) {
    char buf[MAX_LEN];
    size_t len;

    if (!fgets(buf, sizeof(buf), input)) {
        return NULL;
    }
    if ((len = strlen(buf)) == MAX_LEN - 1 && buf[len - 1] != '\n') {
        printf("Line too long from file.");
        return NULL;
    }
    return strdup(buf);
}

char *makeSummary(FILE *input, int summaryNum) {
   char *line = readLine(input, 0); //Get first line
   if (line == NULL)
       return NULL;

   int lineLength = strlen(line);

    if (summaryNum == 1) {
        //Get the last line of file by looping till NULL
        lineNum = 10; 

        free(line);
        line = readLine(input, lineNum);
        //Do more stuff with line
   }
   free(line);
   return NULL;
}

请注意,strdup() 不是标准的,在非 Posix 系统上可能不可用,但很容易实现:

#include <string.h>

char *strdup(const char *s) {
    size_t size = strlen(s) + 1;
    char *p = malloc(size);
    if (p != NULL) {
        memcpy(p, s, size);
    }
    return p;
}