我目前正在为Windows编写一个小的(而且很糟糕)的grep式程序。在其中,我想逐行读取文件并打印出包含密钥的文件。为此,我需要一个函数来读取文件的每一行。由于我不在Linux上,因此无法使用getline
函数,而必须自己实现。
我已经找到了实现此类功能的SO answer。我尝试了一下,它对于“普通”文本文件也能正常工作。但是,如果我尝试读取行长为13000个字符的文件,程序就会崩溃。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char * getline(FILE *f)
{
size_t size = 0;
size_t len = 0;
size_t last = 0;
char *buf = NULL;
do {
size += BUFSIZ; /* BUFSIZ is defined as "the optimal read size for this platform" */
buf = realloc(buf, size); /* realloc(NULL,n) is the same as malloc(n) */
/* Actually do the read. Note that fgets puts a terminal '\0' on the
end of the string, so we make sure we overwrite this */
if (buf == NULL) return NULL;
fgets(buf + last, size, f);
len = strlen(buf);
last = len - 1;
} while (!feof(f) && buf[last] != '\n');
return buf;
}
int main(int argc, char *argv[])
{
FILE *file = fopen(argv[1], "r");
if (file == NULL)
return 1;
while (!feof(file))
{
char *line = getline(file);
if (line != NULL)
{
printf("%s", line);
free(line);
}
}
return 0;
}
这是我正在使用的file。它包含三行简短的内容,而从我的Qt项目之一中读得很长。读取此行时,getline
函数将2次重新分配为1024,并在第3次崩溃。我将printf
放在realloc
周围,以确保它在那里崩溃并且确实可以。
有人可以解释我为什么我的程序崩溃吗?我只是花了几个小时而已,不知道该怎么办。
答案 0 :(得分:2)
在此片段中
size += BUFSIZ;
buf = realloc(buf, size);
if (buf == NULL) return NULL;
fgets(buf + last, size, f);
您添加 size + BUFSIZ
并进行分配,但随后您读到的内容却一样-增加了! – size
。从本质上讲,您阅读的字符比每次分配的字符要多。初次使用size = BUFSIZ
时,您会准确地读取size
/ BUFSIZ
个字符。如果行长于此(最后一个字符不是\n
),则增加内存的大小(size += BUFSIZ
),但您还读取其(新)< em>总计大小–您已经处理了最后size
个字节。
分配的内存每个循环以BUFSIZE
增长,但是读取的字节数量以BUFSIZE
增长 –一个循环后为BUFSIZE
,之后是两个循环2*BUFSIZE
,依此类推,直到重要内容被覆盖并终止程序为止。
如果您仅读取大小为BUFSIZE
的块,则应该可以。
请注意,您的代码希望最后一行以\n
结尾,但不一定总是如此。您可以通过其他测试来了解这一点:
if (!fgets(buf + last, size, f))
break;
因此您的代码将不会尝试读取输入文件末尾的内容。