2016-12-30 87 views
2

这个问题是关于POSIX C函数getlinePOSIX getline() - EOF上的行缓冲区状态?

该文档指出getline在出错时(包括EOF)返回-1,但它没有说明在这些情况下变为lineptrn
我知道某些错误可能会以不同的方式处理 - 例如失败的realloc - 但EOF如何? lineptrn仍然保留其原始值?它是具体实现吗?未定义的行为?

回答

4

如果getline返回错误(EOF是此函数中的错误)。不应使用缓冲区中的数据。

EOF如果函数读取至少1个字节,则不得返回,请注意,在某些情况下函数可能返回0。

此外,manual说清楚:

这个缓冲区应该由就算函数getline()失败的用户程序中解脱出来。


在这两种情况下,一个成功的呼叫,* lineptr和* N将被更新 以反映缓冲区地址,分别分配大小。

这句话可以解释为缓冲区只在成功的调用时更新。


在我看来,程序应该记录这个错误并继续读取已经读取的数据。注意:使用feof()来知道流是否已到达结尾。

+0

我同意当'getline'失败时缓冲区应该被释放,但是在失败时仍然没有提及缓冲区内容的状态。无论哪种方式,在'-1'返回定义好之后听起来不像访问缓冲区,所以最好不要依赖它。 –

+0

@ Mr.Llama顺便说一句,我不明白你为什么想知道'EOF'。为什么你要保存数据到getline()'没有错误返回时已经解析过的缓冲区中?思考完后,这看起来像是一个XY问题。 – Stargateur

+0

我有一个单行缓冲区,我想在EOF之前打印最后一行。问题是,如果'getline'为EOF返回-1,我不能保证我的行缓冲区对于打印仍然有效。现在我正在通过使用两行缓冲区来解决它。 –

3

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

+0

“所以当你到达EOF”可能更清楚地理解为“因此,当函数返回-1因为EOF”,因为即使读取和写入字节到缓冲区EOF可以达到。 –

+1

@ChronoKitsune是的,这可能更好,虽然POSIX文档说得很清楚。我可能不应该试图解释文档。 – Stuart

1

lineptrn的值是特定于实现的。 getline()函数在读取EOF时可能会或可能不会重新分配缓冲区。

我以Illumos,NetBSD和FreeBSD为例。我看getdelim(),因为所有3个系统都有getline()调用带分隔符'\ n'的getdelim()。

  • Illumos getdelim()在它调用__filbuf来读取文件之前,总是尝试使用至少128字节的缓冲区。所以,如果你通过*lineptr = NULL并且它读取EOF,你会回到*n = 128*lineptr指向128字节的垃圾。
  • NetBSD getdelim()始终调用__srefill读取文件,然后再尝试进行任何重新分配。如果它读取EOF,则返回与您通过的相同的*lineptr。如果您通过了*lineptr = NULL,NetBSD确实设置了*n = 0
  • FreeBSD getdelim()也会在重新分配之前读取,但如果它读取EOF,则会在缓冲区中放入一个'\ 0'(用于空字符串)。如果*lineptr为NULL,FreeBSD会分配一个1字节的缓冲区。这与NetBSD和Illumos不同,因为这些系统不会在缓冲区中放入空字符串。

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