The restrictions on reading and writing a sequence controlled by an object of class
basic_filebuf<charT, traits> are the same as for reading and writing with the
Standard C library FILEs.
当然C++是兼容C的,C标准也有类似以下声明:
When a file is opened with update mode . . ., both input and output may be performed on
the associated stream. However, output shall not be directly followed by input without an
intervening call to the fflush function or to a file positioning function (fseek,
fsetpos, or rewind), and input shall not be directly followed by output without an
intervening call to a file positioning function, unless the input operation encounters endof-file.
所以,结果以下场景就会导致未定义行为:
Receiving input from a stream directly following an output to that stream without an intervening call to std::basic_filebuf::seekoff() if the file is not at end-offile
Outputting to a stream after receiving input from that stream without a call to std::basic_filebuf::seekoff() if the file is not at end-of-file
title: CERT C++编码规范翻译(FIO) date: 2017-08-09 09:25:46 tags:
C/C++
文件IO
FIO50-CPP. 在使用文件流输入输出的时候不要不使用中介定位调用
严重程度:低。如果在使用文件流做输入输出的时候没有调用中介flush和中介定位那么就是未定义行为。
C++标准[filebuf]有如下声明:
当然C++是兼容C的,C标准也有类似以下声明:
所以,结果以下场景就会导致未定义行为:
Receiving input from a stream directly following an output to that stream without an intervening call to std::basic_filebuf::seekoff() if the file is not at end-offile
Outputting to a stream after receiving input from that stream without a call to std::basic_filebuf::seekoff() if the file is not at end-of-file
代码样例对比
以上代码通过文件流试图把"Output some data"写入文件尾,然后并把该字符串又重新读出到str对象中,然而,这输入输出的中间并没有调用中介定位函数,所以行为是未定义的。所以改成以下:
以上代码通过std::basic_istream::seekg()把文件流指针调整到了文件的开头,这样才能读取到写入的字符串。
FIO51-CPP. 当不需要操作文件的时候一定要关闭文件
严重程度: 中等。容易导致系统资源浪费,造成程序不正常终止。
对std::basic_filebuf::open()的调用一定要有std::basic_filebuf::close()来关闭文件,至少都要在程序结束之前关闭。
注意,std::basic_ifstream, std::basic_ofstream和std::basic_fstream这三个类底层都依赖std::basic_filebuf对象提供的open和close来打开关闭文件。
代码样例对比
以上代码显然有问题,因为用文件流对象打开了一个文件,但是file对象没有正确关闭,因为代码用std::terminate()强制终止了程序,导致file对象的析构函数没有调用,自然就没有正确关闭文件。std::terminate()本质上是调用了std::abort()才导致的问题。
当然,如果非要在f()函数中强制终止程序,那么需要手工保证文件关闭,不能依赖RAII来关闭资源:
当然,还可以通过RAII机制来关闭文件,这样的方式是C++主推的一种手段,方便安全: