前几天我正在编写一个程序,我使用getline()
函数,我意识到以前从未想过的东西,并且无法在网上找到任何关于它的东西。
根据手册页中getline
的描述:
说明
getdelim()
函数从流中读取一行,由字符分隔符分隔。getline()
函数等效于getdelim()
,换行符为分隔符。除非到达文件的末尾,否则分隔符字符作为行的一部分包含在内。调用者可以为
*linep
中的行提供指向malloced缓冲区的指针,以及*linecapp
中该缓冲区的容量。这些函数根据需要扩展缓冲区,就像通过realloc()
一样。如果linep
指向NULL
指针,则将分配新缓冲区。在任何一种情况下,*linep
和*linecapp
都会相应更新。
通常当我使用这个函数时,我总是将我自己的缓冲区malloc并传递给getline函数,但在阅读之后我意识到这不是必需的,因为只会创建一个。
我的问题是:我有没有理由创建自己的缓冲区,然后将其传递给getline,而不是仅传递NULL
并让getline处理缓冲区?
我能想到的唯一原因是,如果你想控制缓冲区的大小,但这看起来并不正确,因为它说它会根据需要调整缓冲区的大小。
我什么时候应该使用自己的缓冲区?何时我应该让getline处理缓冲区的创建?
答案 0 :(得分:4)
getline()
之前进行分配是有意义的。
1)许多getline()
重新分配方案是班轮。也就是说,它将分配N个字节的缓冲区(例如256,1k,4k)。然后,如果它不够大,它将尝试2 * N,3 * N,4 * N,5 * N等。如果由于某种原因,代码需要定期大的缓冲区需求,在调用之前分配一个大缓冲区{{ 1}}将阻止getline()
重复重置小缓冲区。潜力,如果可疑,效率提高。
getline()
2)在调用 size_t size = 10000;
char *buf = mallc(size);
ssize_t numchar = getline(&buf, &size, ...);
之前,代码是否需要或有可用的工作缓冲区,可以使用它。
getline()
3)重复通话。这包括重复调用 size_t size = 100;
char *buf = mallc(size);
...
foo(buf, size);
...
// No need for these steps
// free(buf);
// size = 0;
// buf = NULL;
...
ssize_t numchar = getline(&buf, &size, ...);
...
free(buf);
的循环。无需在循环内释放,等待循环完成。 @Alan Stokes
getline()
Q2:我什么时候应该使用自己的缓冲区?何时我应该让getline处理缓冲区的创建?
A2:当代码当然需要或从中受益时,分配您自己的缓冲区。否则让 // do not use this
while (some_condition) {
size_t size = 0;
char *buf = NULL;
ssize_t numchar = getline(&buf, &size, ...);
foo(numchar, buf,size);
free(buf);
}
// instead, use this model
size_t size = 0;
char *buf = NULL;
while (some_condition) {
ssize_t numchar = getline(&buf, &size, ...);
foo(numchar, buf,size);
}
free(buf);
去做。
答案 1 :(得分:0)
没有理由,缓冲区是realloc
d根据需要,您应该自己free
。因此,您可以通过NULL
确保通过length == 0
。
我没有看到使用您自己分配的缓冲区的任何情况,无论如何都会使用malloc
,getline
getdelim
也会使用
当然,如果您传递足够大的缓冲区,则会阻止在每个realloc
上调用getline
,但您可以使用valgrind
进行测试,而对于最常见的情况,则会尽可能少可能致电realloc
。