I have a very simple program
#include <iostream>
#include <fstream>
void CHECK(std::iostream& s)
{
std::cout << "good(): " << s.good()
<< " fail(): " << s.fail()
<< " bad(): " << s.bad()
<< " eof(): " << s.eof() << std::endl;
}
int main(int argc, const char * argv[])
{
std::fstream ofs("test.txt", std::ios::out | std::ios::trunc);
std::cout << "opened" << std::endl;
CHECK(ofs);
ofs << "Hello, World!\n";
CHECK(ofs);
ofs.close();
std::cout << "closed" << std::endl;
CHECK(ofs);
ofs << "Hello, World!\n";
std::cout << "after operation" << std::endl;
CHECK(ofs);
return 0;
}
With libc++
I get the following last line:
good(): 1 fail(): 0 bad(): 0 eof(): 0
Expected (or with libstdc++
):
good(): 0 fail(): 1 bad(): 1 eof(): 0
I have tested on OSX with Xcode 9.4.1 (or on Linux), but always the same. Can anybody explain me the situation here? Also the file content was not updated, because already closed. Why is the stream still good after closing and further operation?
What I suspect is happening is that the operations are stuffing the data into the rdbuf
associated with the stream. That succeeds, as long as there is room in the buffer. Eventually, the buffer gets full, and the stream attempts to write to the file (which is closed) and that fails.
You can test that by making the last bit a loop:
ofs.close();
std::cout << "closed" << std::endl;
CHECK(ofs);
for (int i = 0; i < 500; ++i)
{
ofs << "Hello, World!\n";
std::cout << i << " ";
CHECK(ofs);
}
std::cout << "after operation" << std::endl;
On my machine, it fails after about 300 - and forever after that. Is this correct behavior? (or even standards-compliant?) I don't know.
[ Later: If I change libc++ do set the buffer size to 0 upon close, then the first write fails - so that suggests that my analysis is correct. However, I still haven't found anything in the standard about what this 'should' do. ]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With