When Will Ofstream::Open Fail

Why ofstream would fail to open the file in C++? Reasons?

Too many file handles open? Out of space? Access denied? Intermittent network drive problem? File already exists? File locked? It's awfully hard to say without more details. Edit: Based on the extra details you gave, it sounds like you might be leaking file handles (opening files and failing to close them and so running out of a per-process file handle limit).

I assume that you're familiar with using the exceptions method to control whether iostream failures are communicated as exceptions or as status flags.

In my experience, the iostream classes give very little details on what went wrong when they fail during an I/O operation. However, because they're generally implemented using lower-level Standard C and OS API functions, you can often get at the underlying C or OS error code for more details. I've had good luck using the following function to do this.

std::string DescribeIosFailure(const std::ios& stream)
{
std::string result;

if (stream.eof()) {
result = "Unexpected end of file.";
}

#ifdef WIN32
// GetLastError() gives more details than errno.
else if (GetLastError() != 0) {
result = FormatSystemMessage(GetLastError());
}
#endif

else if (errno) {
#if defined(__unix__)
// We use strerror_r because it's threadsafe.
// GNU's strerror_r returns a string and may ignore buffer completely.
char buffer[255];
result = std::string(strerror_r(errno, buffer, sizeof(buffer)));
#else
result = std::string(strerror(errno));
#endif
}

else {
result = "Unknown file error.";
}

boost::trim_right(result); // from Boost String Algorithms library
return result;
}

Detecting reason for failure to open an ofstream when fail() is true

Unfortunately, there is no standard way of finding out exactly why open() failed. Note that sys_errlist is not standard C++ (or Standard C, I believe).

Does std::ofstream guarantee the old open file will be closed if opening new one?

The second and subsequent calls will fail.

[filebuf.members]

basic_filebuf* open(const char* s, ios_base::openmode mode);

2 Effects: If is_open() != false, returns a null pointer. Otherwise...

[ofstream.members]

void open(const char* s, ios_base::openmode mode = ios_base::out);

3 Effects: Calls rdbuf()->open(s, mode | ios_base::out). If that function does not return a null pointer calls clear(), otherwise calls setstate(failbit)

fstream !fail() and is_open()

Any solution will actually be fairly complicated, because you'll
normally want to handle different types of errors differently.
If you cannot open the file, for example, you want to tell the
user that, and not just that the output failed. Not being able
to open the file is an error that you really expect. On the
other hand, if a write operation fails, you want a different
error handling.

Thus, I would recommend checking is_open immediately after
trying to open the file, and handling the error appropriately
then.

Later errors are far rarer, but probably more serious. In many
cases, it's acceptable to only check for the error after the
close, but whenever an error occurs, you should probably delete
the partially written (and thus corrupt) file. The same holds
if your program fails for some other reason when writing the
data: close the file and delete it. (I tend to use an RAII
class for this, with a commit function which is called when
all of the output has finished. The commit closes the file, and
if the close succeeds, sets a flag; if the flag is not set when
the destructor is called, the destructor closes the file,
ignoring any errors, and then deletes it.)

As for using clear(): I can't think of a case where I'd use it
on an output stream. The iostream classes aren't designed for
reuse, and have far too much internal state to be easily reset.
On input, it can be useful, followed by ignore, if there was
a format error, but this consideration doesn't apply to output
streams, so I'd just ignore it. (And of course, once you call
clear, you have no way of knowing whether anything which
preceded it succeeded or not.)



Related Topics



Leave a reply



Submit