Why does ofstream require a flush? - c++

If I run the following code, no file is created at all:
std::ofstream outputFile(strOutputLocation.c_str(), std::ios::binary);
outputFile.write((const char*)lpResLock, dwSizeRes);
outputFile.close();
However, if I add a flush() before the close, it works:
std::ofstream outputFile(strOutputLocation.c_str(), std::ios::binary);
outputFile.write((const char*)lpResLock, dwSizeRes);
outputFile.flush();
outputFile.close();
Does the standard library actually require this, or is it a bug in the Visual C++ CRT?

It's a bug. Reading §27.8.1.10/4, abridged:
void close();
Effects: Calls rdbuf()->close()...
What does rdbuf()->close() do? According to §27.8.1.3/6, abridged, emphasis mine:
basic_filebuf<charT,traits>* close();
If is_open() == false, returns a null pointer. If a put area exists, calls overflow(EOF) to flush characters. ...
That is, it's suppose to flush. (Indeed, the call to flush() ultimately does the same thing.)
Note the call to close() itself isn't needed, as the destructor of basic_ofstream will call close().

Are you checking the file before you exit from the program? OS will buffer all IO, so may not see any data(unless you flush) in the file before you exit.

Related

Can you safely close a file that was never opened?

If I have a std::ofstream that may or may not have been opened, is it safe to try to close regardless? In otherwords does close() do anything nasty (throw exception, etc) if !is_open(). For example
std::ofstream out;
if (some_condition)
{
out.open(path, std::ios::out);
}
After I'm done with the file, can I just say
out.close();
Or should I first check
if (out.is_open())
out.close();
The only description of std::basic_fstream::close on cppreference is
Closes the associated file.
Effectively calls rdbuf()->close(). If an error occurs during operation, setstate(failbit) is called.
It does exactly what cppreference says it will: the failbit will be set, and you can inspect it with the fail() method. For instance, the following prints "fail\n":
#include <iostream>
#include <fstream>
int main(int argc, char ** argv)
{
std::ofstream out;
out.close();
if (out.fail())
std::cout << "fail" << std::endl;
return 0;
}
In terms of interaction with the operating system, there's nothing there to close, but it's otherwise harmless.
From the C++ standard, §27.9.1.4 [filebuf.members], paragraph 6:
basic_filebuf<charT,traits>* close();
Effects: If is_open() == false, returns a null pointer.…
Yes, you can close() the file always, even the file is not opened.
No matter LINUX or Windows, I always close() without thinking they are opened or not.
From LINUX:
void
close()
{
if (!_M_filebuf.close())
this->setstate(ios_base::failbit);
}

What happens if I never call `close` on an open file stream? [duplicate]

This question already has answers here:
do I need to close a std::fstream? [duplicate]
(3 answers)
Closed 7 years ago.
Below is the code for same case.
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
//myfile.close();
return 0;
}
What will be the difference if I uncomment the myfile.close() line?
There is no difference. The file stream's destructor will close the file.
You can also rely on the constructor to open the file instead of calling open(). Your code can be reduced to this:
#include <fstream>
int main()
{
std::ofstream myfile("example.txt");
myfile << "Writing this to a file.\n";
}
To fortify juanchopanza's answer with some reference from the std::fstream documentation
(destructor)
[virtual](implicitly declared)
destructs the basic_fstream and the associated buffer, closes the file
(virtual public member function)
In this case, nothing will happen and code execution time is very less.
However, if your codes runs for long time when you are continuously opening files and not closing, after a certain time, there may be crash in run time.
when you open a file, the operating system creates an entry to represent that file and store the information about that opened file. So if there are 100 files opened in your OS then there will be 100 entries in OS (somewhere in kernel). These entries are represented by integers like (...100, 101, 102....). This entry number is the file descriptor. So it is just an integer number that uniquely represents an opened file in operating system. If your process open 10 files then your Process table will have 10 entries for file descriptors.
Also, this is why you can run out of file descriptors, if you open lots of files at once. Which will prevent *nix systems from running, since they open descriptors to stuff in /proc all the time.
Similar thing should happen in case of all operating system.
Under normal conditions there is no difference.
BUT under exceptional conditions (with slight change) the call to close can cause an expception.
int main()
{
try
{
ofstream myfile;
myfile.exceptions(std::ios::failbit | std::ios::badbit);
myfile.open("example.txt");
myfile << "Writing this to a file.\n";
// If you call close this could potentially cause an exception
myfile.close();
// On the other hand. If you let the destructor call the close()
// method. Then the destructor will catch and discard (eat) the
// exception.
}
catch(...)
{
// If you call close(). There is a potential to get here.
// If you let the destructor call close then the there is
// no chance of getting here.
}
}

Reuse a filestream in C++?

I have a program that takes multiple files as input. What I'm trying to do is use the same filestream? I keep getting an error when trying to open the stream with the second file. Why is not code not valid and creating an error at compile time? argv[2] is a const char*.
error: no match for call to '(std::ifstream) (char*&)'
ifstream fin(argv[1]);
//work with filestream
fin.close();
fin(argv[2]);
//work with filestream
fin.close();
The first line ifstream fin(argv[1]); is evoking ifstream's constructor, and the constructor can only be called once per object. Your code is trying to call it a second time. Try using open() instead:
fin.open(argv[2]);
As an aside, you may also want to call clear() before you reopen your ifstream. The reason for this is that if the first open() (or even close()) fails, error bits on the ifstream will be set, and won't be cleared by close().
Use a local scope:
{
ifstream fin(argv[1]);
//work with filestream
}
{
ifstream fin(argv[2]);
//work with filestream
}
Note that you dont manually need to close the streams, this is handled automatically when they go out of scope.

How to read from a library standard error?

I have a Qt/C++ acpplication which is using a C++ library.
This library has a log mechanism that writes string messages to standard error.
Now, I would like to be able to redirect those messages toward a panel in my Qt tool.
I would like to avoid modifying the library because is adopted by many other clients.
Any idea how to get at runtime these messages?
Having instead the possibility of changing it what could be a good practise for carrying those messages up to the application?
That's very poor library design. However...
How does it write to standard error. If it is outputing to std::cerr,
then you can change the streambuf used by std::cerr, something like:
std::filebuf logStream;
if ( ~logStream.open( "logfile.txt" ) )
// Error handling...
std::streambuf* originalCErrStream = std::cerr.rdbuf();
std::cerr.rdbuf( &logStream );
// Processing here, with calls to library
std::cerr.rdbuf( originalCErrStream ); // Using RAII would be better.
Just don't forget to restore the original streambuf; leaving std::cerr
pointing to a filebuf which has been destructed is not a good idea.
If they're using FILE*, there's an freopen function in C (and by
inclusion in C++) that you can use.
If they're using system level output (write under Unix, WriteFile
under Windows), then you're going to have to use some system level code
to change the output. (open on the new file, close on fd
STDERR_FILENO, and dup2 to set STDERR_FILENO to use the newly
opened file under Unix. I'm not sure it's possible under
Windows—maybe something with ReOpenFile or some combination of
CloseHandle followed by CreateFile.)
EDIT:
I just noticed that you actually want to output to a Qt window. This
means that you probably need a string, rather than a file. If the
library is using std::cerr, you can use a std::stringbuf, instead of
a std::filebuf; you may, in fact, want to create your own streambuf,
to pick up calls to sync (which will normally be called after each
<< on std::cerr). If the library uses one of the other techniques,
the only thing I can think of is to periodically read the file, to see
if anything has been added. (I would use read() in Unix, ReadFile()
in Windows for this, in order to be sure of being able to distinguish a
read of zero bytes, due to nothing having been written since the last
read, and an error condition. FILE* and iostream functions treat a
read of zero bytes as end of file, and will not read further.)
write to stderr is actually a syscall:
write(2, "blahblah ...");
you can redirect file descriptor number 2 to anything (file, pipe, socket):
close(2); // close old stderr
int redirect_target = open(...); // open a file where you want to redirect to
// or use pipe, socket whatever you like
dup2(redirect_target, 2); // copy the redirect_target fd to fd number 2
close(redirect_target);
in your situation, you will need a pipe.
close(2);
int pipefd[2];
pipe2(pipefd);
dup2(pipefd[1], 2);
close(pipefd[1]);
then, everything write to stderr can be obtained by reading pipe[0]:
read(pipe[0], buffer, ...);
If they're using calls to std::cerr, you can redirect this to a std::ostringstream.
#include <iostream>
#include <sstream>
class cerr_redirector
{
public:
cerr_redirector(std::ostream& os)
:backup_(std::cerr.rdbuf())
,sbuf_(os.rdbuf())
{
std::cerr.rdbuf(sbuf_);
}
~cerr_redirector()
{
std::cerr.rdbuf(backup_);
}
private:
cerr_redirector();
cerr_redirector(const cerr_redirector& copy);
cerr_redirector& operator =(const cerr_redirector& assign);
std::streambuf* backup_;
std::streambuf* sbuf_;
};
You can capture the output using:
std::ostringstream os;
cerr_redirector red(os);
std::cerr << "This is written to the stream" << std::endl;
std::cout will be unaffected:
std::cout << "This is written to stdout" << std::endl;
So you can then test your capture is working:
std::cout << "and now: " << os.str() << std::endl;
Or just add the contents of os.str() to your Qt Window.
Demonstration at ideone.
Here I found a complete implemenation of what i needed...
Thanks everybody for the help! :)
Will loading a DLL dynamically reconcile its stderr to a main application? If so, then how...?

Do I need to manually close an ifstream?

Do I need to manually call close() when I use a std::ifstream?
For example, in the code:
std::string readContentsOfFile(std::string fileName) {
std::ifstream file(fileName.c_str());
if (file.good()) {
std::stringstream buffer;
buffer << file.rdbuf();
file.close();
return buffer.str();
}
throw std::runtime_exception("file not found");
}
Do I need to call file.close() manually? Shouldn't ifstream make use of RAII for closing files?
NO
This is what RAII is for, let the destructor do its job. There is no harm in closing it manually, but it's not the C++ way, it's programming in C with classes.
If you want to close the file before the end of a function you can always use a nested scope.
In the standard (27.8.1.5 Class template basic_ifstream), ifstream is to be implemented with a basic_filebuf member holding the actual file handle. It is held as a member so that when an ifstream object destructs, it also calls the destructor on basic_filebuf. And from the standard (27.8.1.2), that destructor closes the file:
virtual ˜basic_filebuf();
Effects: Destroys an object of class basic_filebuf<charT,traits>. Calls close().
Do you need to close the file?
NO
Should you close the file?
Depends.
Do you care about the possible error conditions that could occur if the file fails to close correctly? Remember that close calls setstate(failbit) if it fails. The destructor will call close() for you automatically because of RAII but will not leave you a way of testing the fail bit as the object no longer exists.
You can allow the destructor to do it's job. But just like any RAII object there may be times that calling close manually can make a difference. For example:
#include <fstream>
using std::ofstream;
int main() {
ofstream ofs("hello.txt");
ofs << "Hello world\n";
return 0;
}
writes file contents. But:
#include <stdlib.h>
#include <fstream>
using std::ofstream;
int main() {
ofstream ofs("hello.txt");
ofs << "Hello world\n";
exit(0);
}
doesn't. These are rare cases where a process suddenly exits. A crashing process could do similar.
No, this is done automatically by the ifstream destructor. The only reason you should call it manually, is because the fstream instance has a big scope, for example if it is a member variable of a long living class instance.