This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.

### 622. behavior of `filebuf` dtor and `close` on error

Section: 29.10.5.4 [fstream.members] Status: CD1 Submitter: Martin Sebor Opened: 2007-01-20 Last modified: 2016-01-28

Priority: Not Prioritized

View all issues with CD1 status.

Discussion:

`basic_filebuf` dtor is specified to have the following straightforward effects:

> Effects: Destroys an object of class `basic_filebuf`. Calls `close()`.

`close()` does a lot of potentially complicated processing, including calling `overflow()` to write out the termination sequence (to bring the output sequence to its initial shift state). Since any of the functions called during the processing can throw an exception, what should the effects of an exception be on the dtor? Should the dtor catch and swallow it or should it propagate it to the caller? The text doesn't seem to provide any guidance in this regard other than the general restriction on throwing (but not propagating) exceptions from destructors of library classes in 16.4.6.13 [res.on.exception.handling].

Further, the last thing `close()` is specified to do is call `fclose()` to close the `FILE` pointer. The last sentence of the Effects clause reads:

> ... If any of the calls to `overflow` or `std::fclose` fails then `close` fails.

This suggests that `close()` might be required to call `fclose()` if and only if none of the calls to `overflow()` fails, and avoid closing the `FILE` otherwise. This way, if `overflow()` failed to flush out the data, the caller would have the opportunity to try to flush it again (perhaps after trying to deal with whatever problem may have caused the failure), rather than losing it outright.

On the other hand, the function's Postcondition specifies that `is_open() == false`, which suggests that it should call `fclose()` unconditionally. However, since Postcondition clauses are specified for many functions in the standard, including constructors where they obviously cannot apply after an exception, it's not clear whether this Postcondition clause is intended to apply even after an exception.

It might be worth noting that the traditional behavior (Classic Iostreams `fstream::close()` and C `fclose()`) is to close the `FILE` unconditionally, regardless of errors.

[ See 397 and 418 for related issues. ]

Proposed resolution:

After discussing this on the reflector (see the thread starting with c++std-lib-17650) we propose that `close()` be clarified to match the traditional behavior, that is to close the `FILE` unconditionally, even after errors or exceptions. In addition, we propose the dtor description be amended so as to explicitly require it to catch and swallow any exceptions thrown by `close()`.

Specifically, we propose to make the following edits in 29.10.2.4 [filebuf.members]:

>     basic_filebuf<charT,traits>* close();

> Effects: If `is_open() == false`, returns a null pointer. If a put area exists, calls `overflow(traits::eof())` to flush characters. If the last virtual member function called on `*this` (between `underflow`, `overflow`, `seekoff`, and `seekpos`) was `overflow` then calls `a_codecvt.unshift` (possibly several times) to determine a termination sequence, inserts those characters and calls `overflow(traits::eof())` again. Finally, regardless of whether any of the preceding calls fails or throws an exception, the function it closes the file ("as if" by calling `std::fclose(file)`).334) If any of the calls made by the function to `overflow` or, including `std::fclose`, fails then `close` fails by returning a null pointer. If one of these calls throws an exception, the exception is caught and rethrown after closing the file.

And to make the following edits in 29.10.2.2 [filebuf.cons].

>     virtual ~basic_filebuf();

> Effects: Destroys an object of class `basic_filebuf<charT,traits>`. Calls `close()`. If an exception occurs during the destruction of the object, including the call to `close()`, the exception is caught but not rethrown (see 16.4.6.13 [res.on.exception.handling]).