radix radix - 29 days ago 24
C++ Question

c++ ofstream: evaluate close() error

I'm trying to figure out the reason of a failed

ofstream::close()
and encountered some behaviour I don't understand.

I use an
std::ofstream
and
std::copy()
to write data to a stream, then I write the file by using
close()
. If I provoke an error (e.g. the filesystem is full), the
failbit
is set by
close()
, but I'd like to get a more detailed error description.

So far I thought that
errno
is always set if a system call fails. However
errno
says
Success
if I check instantly after
close()
fails.

I'm sure a system call is used when
close()
ing the stream because it will write the file to the filesystem, but then how is it possible that
errno
doesn't tell anything about the problem? So:


  • Does
    ofstream::close()
    not use any system calls?



If I explicitly call
flush()
after
std::copy()
, then
errno
is set properly

No space left on device


and the
failbit
is set. The subsequent call of
close()
also sets the failbit. Surprisingly
errno
is reset to
success
.

As per
errno
manpage:

errno is never set to zero by any system call or library function


and I don't see which other function would reset
errno
.


  • Does
    ofstream::close()
    explicitly reset
    errno
    in case it succeeds?



The documentation on
ofstream
I've found doesn't say anthing about
errno
.

Tested with Linux x86 g++ 4.7.3.

Answer

Indeed ofstream::close() makes multiple system calls. Even though system calls and C library functions do not set errno to zero, C++ libraries may. At least some implementation of ofstream::close() sets errno to 0. See the comment below.

My advice is to pay attention to the documentation on the things you use, and do not make assumptions. In this case, as you pointed out the documentation of ofstream::close() does not say anything about errno, so you should not make any assumption of errno after calling ofstream::close(). On the other hand, C functions such as close(fd) specifically mention errno in the documentation. So if you really need errno, use C functions instead.