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

时间:2017-09-02 11:48:40

标签: c file memory-leaks fgets

我正在尝试从文件中读取一行并返回该行。但是,我不断收到内存泄漏,丢失4000个字节,比alloc更少一个。我不知道为什么会这样。以下是功能。

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);
}

3 个答案:

答案 0 :(得分:0)

当你的函数需要返回它时它是free(string)(这是有意义的),所以除非你没有发布的代码的某些部分是free - 它(并且没有)这里的任何人都可以告诉你,出于明显的原因,这是你的泄密。

答案 1 :(得分:0)

非常感谢@WhozCraig。问题是使用readLine的函数在实际读取所需的行号之前没有释放Line。现在解决了这一切,一切正常。

答案 2 :(得分:0)

您的代码存在一些问题:

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

  • 此外,根据定义,string的长度小于MAX_LEN,您的测试始终为false。您可能想要检查该行是否以换行符结束以检测截断。

  • 您返回EXIT_SUCCESS,但该函数返回char *。编译器未检测到这种差异,因为EXIT_SUCCESS被定义为0,因此return EXIT_SUCCESS;return NULL;相同。

  • 函数makeSummary中的
  • ,您似乎用下一次调用line时返回的指针覆盖readLine()。您必须free(line);之前致电line = readLine(input, 0)

  • 你在rewind()中拨打readLine(),所以你继续读取输入文件中的同一行,除非找不到文件(例如终端),如果你正在阅读一个普通的文件,你永远不会到达终点。

这是一个分配较少字节的修改版本:

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;
}