POSIX getline() - 在EOF时的行缓冲状态是什么?

4
这个问题涉及到 POSIX C 函数 getline
文档说明说,getline 在出错时(包括 EOF)返回 -1,但它没有说明在这些情况下 lineptrn 会发生什么。
我明白有些错误可能会有不同的处理方式 - 比如 realloc 失败了 - 但是 EOF 呢? lineptrn 是否仍保留原始值? 这是实现特定的吗? 是未定义的行为吗?
3个回答

5
如果getline返回错误(在此函数中,EOF是一种错误),则不应使用缓冲区中的数据。
如果函数读取至少1个字节,则不能返回EOF,注意该函数在某些情况下可能返回0。
此外,manual明确指出:
用户程序应该释放此缓冲区,即使getline()失败。
无论哪种情况,在成功调用时,*lineptr和*n将被更新以反映缓冲区地址和已分配大小。这句话可以解释为仅在成功调用时才会更新缓冲区。
在我看来,程序应该记录此错误并继续使用已经读取的数据。注意:使用 feof() 来判断流是否已到达结尾。

我同意当 getline 失败时应该释放缓冲区,但这仍然无法说明缓冲区在失败时的内容状态。无论如何,在返回 -1 后访问缓冲区似乎都没有定义良好,所以最好不要依赖它。 - Mr. Llama
顺便说一下,我真的不明白为什么你想知道EOF的原因。当getline()没有错误返回时,为什么要保留已经解析的缓冲区数据呢?经过思考,这看起来像是一个XY问题。 - Stargateur
我有一个单行缓冲区,我想在 EOF 之前打印整个最终行。问题是,如果 getline 返回 -1 表示 EOF,我不能保证我的行缓冲区仍然有效以供打印。目前,我通过使用两个行缓冲区来解决这个问题。 - Mr. Llama
1
GNU文档https://www.gnu.org/software/libc/manual/html_node/Line-Input.html说:“如果发生错误或到达文件结尾而没有读取任何字节,则getline返回-1。”这似乎意味着即使最后一行没有以换行符结束,该函数也将返回读取的字符数(而不是-1)。另一方面,Linux文档没有说明这一点,因此您可能应该创建一个文本文件,其中最后一行没有以换行符结束,并测试会发生什么。 - Stuart
@Stuart 这个人也说了这句话:“如果找到换行符,缓冲区将以空字符结尾,并包含换行符。” - Stargateur
显示剩余4条评论

3
如果你查看这些POSIX文档 http://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html,你会发现该函数在读取流的最后一行时如果EOF发生且该行没有换行符(即最后一行没有换行符),并不会返回-1。所以当你到达EOF时,缓冲区的内容并不重要,因为getline不会将任何内容写入其中。

“所以,当您到达EOF”可能更清晰地理解为“所以,当函数因EOF返回-1” ,因为即使在读写缓冲区的字节时也可能遇到EOF。 - user539810
1
@ChronoKitsune 是的,那可能更好,尽管 POSIX 文档已经说得很清楚了。我可能不应该试图解释这些文档。 - Stuart

1
< p > lineptrn 的值是特定于实现的。当 getline() 函数读取 EOF 时,它可能会或可能不会重新分配缓冲区。

我举例说明了 Illumos、NetBSD 和 FreeBSD。我看 getdelim() 是因为这三个系统都使用 delimiter '\n' 调用 getline()。

  • Illumos getdelim()总是尝试使用至少128字节的缓冲区,然后才调用__filbuf读取文件。因此,如果您传入*lineptr = NULL并且它读取到EOF,则会返回*n = 128和指向128个垃圾字节的*lineptr
  • NetBSD getdelim()总是调用__srefill读取文件,然后再尝试重新分配内存。如果它读取到EOF,则会返回与您传入的相同的*lineptr。如果您传入*lineptr = NULL,NetBSD会将*n = 0设置为零。
  • FreeBSD getdelim()在重新分配内存之前也会读取,但如果它读取到EOF,则会在缓冲区中放置单个'\0'(表示空字符串)。如果*lineptr为NULL,则FreeBSD会分配一个1字节的缓冲区。这与NetBSD和Illumos不同,因为那些系统不会在缓冲区中放置空字符串。

总之,当getline()读取到EOF时,*lineptr的值可能会改变,也可能不会改变,并且它可能指向一个空字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接