1

I am a bit confused about this question:

What would happen with c code if you would try to close stdin or stdout instead of a file?

My guess is that the buffer will be depleted, am I right?

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
alpha01
  • 11
  • 3
  • 4
    What do you mean by "depleted"? You won't be able to use the closed stream without invoking undefined behavior. – Eugene Sh. Sep 22 '22 at 18:20
  • 2
    What makes you think `stdin` and `stdout` are not files? Or else, in what sense do you mean "instead of a file", and why do you think it would make a difference? – John Bollinger Sep 22 '22 at 18:24
  • Duplicate: [Is close/fclose on stdin guaranteed to be correct?](https://stackoverflow.com/q/288062/10871073) – Adrian Mole Sep 22 '22 at 18:26

3 Answers3

2

The C standard does not say there is any special treatment for closing stdin or stdout or any special restrictions on closing them.

The documentation for fclose in C 2018 7.21.5.1 2 says:

A successful call to the fclose function causes the stream pointed to by stream to be flushed and the associated file to be closed. Any unwritten buffered data for the stream are delivered to the host environment to be written to the file; any unread buffered data are discarded. Whether or not the call succeeds, the stream is disassociated from the file and any buffer set by the setbuf or setvbuf function is disassociated from the stream (and deallocated if it was automatically allocated).

“Deplete” is not a term used in the C standard. When used about an input buffer, it refers to the program drawing data from the buffer that has been previously filled with input (such as from a user typing a line of text in a terminal) to the point where there is no data left in the buffer. Given the behavior of fclose, the data in the buffer is discarded, not depleted.

Closing the Unix or other operating system file that is used to implement the C stream, as with close instead of fclose, might result in the C buffer remaining, so that further C library calls such as getchar() will draw data from the buffer until it is depleted, after which such routines are likely to report an I/O error.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
1

The stdin and stdout (and stderr) objects declared by stdio.h are specified to have type FILE * and to initially refer to the program's standard input, standard output, and standard error streams, respectively. Roughly speaking, you can do anything with them that you can do with any other stream, including close them. After closure, they are no longer valid streams for I/O, including for those I/O functions that target them implicitly (printf, scanf, ...).

Therefore, if you attempt to use one of them for I/O after having closed it, you can expect that your I/O operation will fail. The specific manifestation of that depends in part on the specific function with which you attempt the I/O operation.

Note also, by the way, that the C naming of type FILE reflects the Unix model of the world that all I/O endpoints are modeled as "files". Where you mean a persistent, named chunk of data accessible via a filesystem on a local storage device, you can use the term "regular file". Even then, it is important to distinguish between a C stream, represented by a C object of type FILE, and the underlying data on the storage device.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

When a program starts up, the identifiers stdin, stdout, and stderr are guaranteed to hold the addresses of file objects associated with those streams. When a program terminates, an implementation will do whatever is necessary to close the streams, *but there is no guarantee that it will use the current values of stdin, stdout, and stderr for that purpose.

An implementation may document that if a program does something like:

void swap_stdout(FILE *file_to_use_instead)
{
  FILE *old_stdout = stdout;
  stdout = file_to_use_instead;
  fclose(old_stdout);
}

then the FILE whose address was stored into stdout will be closed when the program terminates, but absent such a specification it is possible that closing stdout would result in the storage that had been assigned to that FILE being reused to hold something else, and the program trying to interpret that other object as a FILE when the program terminates.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • 2
    The C standard does not specify any special treatment for `stdint`, `stdout`, or `stderr`, when a program terminates, whether by those names or otherwise. When a hosted program terminates, “… all open streams with unwritten buffered data are flushed, all open streams are closed, and all files created by the tmpfile function are removed” (C 2018 7.22.4.4 4). So, if a standard stream is open, it is closed, like any other stream. If it is not open, it is not closed, like any other stream. – Eric Postpischil Sep 22 '22 at 18:53
  • @EricPostpischil: The Standard may not specify special treatment, but that doesn't mean that implementations never target environments where such streams *are* "special". While the Committee tried to avoid mandating anything inconsistent with how any underlying execution environments behave, C implementations are ultimately going to be bound by the semantics of their execution environments regardless of anything the Standard might say. If an execution uses e.g. numeric file handles, opens the standard streams before launching an executable, and closes them after an executable exits, ... – supercat Sep 22 '22 at 19:17
  • ...then software wanting to avoid a "double close" may need to use a platform-specific means of notifying the platform that it shouldn't close `stdout` when the program exits. The Standard may not provide for such a thing, but if an execution environment would require it, an implementation for such a platform may need to do so as well. – supercat Sep 22 '22 at 19:19
  • The only thing a C implementation has to do to conform to the standard in this regard on a platform that has numeric file handles is maintain a list of streams it has open. – Eric Postpischil Sep 22 '22 at 19:22