Issue 622: behavior of filebuf dtor and close on error (original) (raw)


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: 31.10.6.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 classbasic_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.14 [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 orstd::fclose fails then close fails.

This suggests that close() might be required to callfclose() if and only if none of the calls tooverflow() fails, and avoid closing the FILEotherwise. 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 thatis_open() == false, which suggests that it should callfclose() 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(i) and 418(i) 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 FILEunconditionally, 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 31.10.3.4 [filebuf.members]:

basic_filebuf<charT,traits>* close();

Effects: If is_open() == false, returns a null pointer. If a put area exists, callsoverflow(traits::eof()) to flush characters. If the last virtual member function called on *this (betweenunderflow, overflow, seekoff, and seekpos) was overflow then callsa_codecvt.unshift (possibly several times) to determine a termination sequence, inserts those characters and callsoverflow(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 callingstd::fclose(file)).334) If any of the callsmade by the functionto overflowor, 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 31.10.3.2 [filebuf.cons].

virtual ~basic_filebuf();

Effects: Destroys an object of classbasic_filebuf<charT,traits>. Callsclose(). 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.14 [res.on.exception.handling]).