C:逐行读取文件的fgets - >提供更少的内存?

时间:2014-08-22 14:40:44

标签: c

我尝试在C中逐行读取文件(但由于某些原因,我希望在最后将这些行连接成一个字符串!)。

int max_line_length, finish_length, current_length;
max_line_length = finish_length = 50000;
current_length = 0;
line = malloc(sizeof(char) * max_line_length);
finished_line = malloc(sizeof(char) * finish_length);

while (fgets(line, max_line_length, file) != NULL) {

  if (line[strlen(line)-1] == '\n') {
    int len = strlen(line);
    char new_part[len];
    strncpy(new_part, line, len - 1);
    new_part[len - 1] = '\0';

    if ((current_length + (len - 1)) > finish_length) {
      while ((current_length + (len - 1)) > finish_length) finish_length*=2;
      finish_line = realloc(sizeof(char)*finish_length);
    }
    current_length+= strlen(new_part);
    strncat(finish_line, new_part, strlen(new_part));
    line[0] = '\0';
  } else {
    max_line_length *= 2;
    line = realloc(sizeof(char) * max_line_length);
  }
}

所以我检查是否读取了换行符,如果没有,它应该意味着没有足够的内存,所以我重新分配它,然后它会被再次读取,对吧?

我不知道我在这里想念的是什么,但是valgrind抱怨说:

4,096 bytes in 1 blocks are definitely lost in loss record 111 of 114  
at 0x47F1: malloc (vg_replace_malloc.c:302)  
==901==    by 0x180915: fgets (in /usr/lib/system/libsystem_c.dylib) 

在我打电话给fgets的那一行!

但是我释放了两个方法,即方法结尾处的line和finished_line。有人看到我在这里错过了什么???

1 个答案:

答案 0 :(得分:0)

参见realloc的定义:

void *realloc(void *ptr, size_t size);

在您的情况下,您在调用realloc时不提供任何ptr参数。对我来说,这甚至都没有编译:

  

错误:函数'realloc'的参数太少

Realloc返回指向新分配内存的指针。您应该将旧指针传递给realloc并使其返回到新指针,如:

char* new_finished_line = NULL;
new_finished_line = realloc(finished_line, sizeof(char)*finish_length);
/* if realloc was successful, it already freed finished_line pointer
 * and it returned to new_finished_line */
if (new_finished_line != NULL) {
    finished_line = new_finished_line;
}
/* if new_finished_line is NULL, then finished line is still allocated */
else {
    free(finished_line);
    printf("realloc error\n");
    exit(1);
}

但是,经过一些语法修复后,我的机器上的版本没有使内存泄漏。也许想想重新设计你的算法?您可以尝试使用下面的代码,其中file由char读取char,如果读取了换行符,则将空间写入缓冲区。实现这一目标的方法有很多种。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* read_my_file(char* name) {
    char* store;
    char* new_store = NULL;
    int SIZE = 10;
    int x;
    int i = 0;
    store = malloc(SIZE);
    FILE* fp = fopen(name, "r");
    while (( x = fgetc(fp) ) != EOF) {
        if (x == '\n') {
            store[i] = ' ';
        }
        else {
            store[i] = x;
        }
        if (i > SIZE - 2) {
            SIZE *= 2;
            new_store = realloc(store, SIZE);
            if (new_store != NULL) {
                store = new_store;
            }
            else {
                fprintf(stderr, "realloc error");
                free(store);
                exit(1);
            }
        }
        i++;
    }
    store[i] = '\0';
    fclose(fp);
    return store;
}

int main(void)
{
    char* container = read_my_file("YOUR_FILE_TO_READ.txt");
    printf("%s\n",container);
    free(container);
    return 0;
}

我的算法可能不是最好的算法,我只想表明有很多方法可以做到这一点。