Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU-getline: strange behaviour about EOF

Tags:

c

linux

eof

Test

In order to find the behaviour of getline() when confronted with EOF, I wrote the following test:

int main (int argc, char *argv[]) {
    size_t max = 100;
    char *buf = malloc(sizeof(char) * 100);
    size_t len = getline(&buf, &max, stdin);
    printf("length %zu: %s", len, buf);
}

And input1 is:

abcCtrl-DEnter

Result:

 length 4: abc  //notice that '\n' is also taken into consideration and printed

Input2:

abcEnter

Exactly same output:

 length 4: abc

It seems that the EOF is left out out by getline()

Source code

So I find the source code of getline() and following is a related snippet of it (and I leave out some comments and irrelevant codes for conciseness):

 while ((c = getc (stream)) != EOF)
{
  /* Push the result in the line.  */
  (*lineptr)[indx++] = c;

  /* Bail out.  */
  if (c == delim)             //delim here is '\n'
   break;
}

/* Make room for the null character.  */
if (indx >= *n)
{
  *lineptr = realloc (*lineptr, *n + line_size);
  if (*lineptr == NULL)
   return -1;
  *n += line_size;
}

/* Null terminate the buffer.  */
(*lineptr)[indx++] = 0;

 return (c == EOF && (indx - 1) == 0) ? -1 : indx - 1;

Question

So my question is:

  • why length here is 4 (as far as I can see it should be 5)(as wiki says, It won't be a EOF if it not at the beginning of a line)

A similar question:EOF behavior when accompanied by other values but notice getline() in that question is different from GNU-getline

I use GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2

like image 857
Tony Avatar asked Oct 21 '22 02:10

Tony


1 Answers

Ctrl-D causes your terminal to flush the input buffer if it isn’t already flushed. Otherwise, the end-of-file indicator for the input stream is set. A newline also flushes the buffer.

So you didn't close the stream, but only flushed the input buffer, which is why getline doesn't see an end-of-file indicator.

In neither of these cases, a literal EOT character (ASCII 0x04, ^D) is received by getline (in order to do so, you can type Ctrl-VCtrl-D).

Type

abcCtrl-DCtrl-D

or

abcEnterCtrl-D

to actually set the end-of-file indicator.

From POSIX:

Special characters

  • EOF

Special character on input, which is recognized if the ICANON flag is set. When received, all the bytes waiting to be read are immediately passed to the process without waiting for a <newline>, and the EOF is discarded. Thus, if there are no bytes waiting (that is, the EOF occurred at the beginning of a line), a byte count of zero shall be returned from the read(), representing an end-of-file indication. If ICANON is set, the EOF character shall be discarded when processed.

FYI, the ICANON flag is specified here.

like image 170
mafso Avatar answered Oct 24 '22 11:10

mafso