Get std::fstream failure error messages and/or exceptions
From checking it out I found that also errno
and also GetLastError()
do set the last error and checking them is quite helpful. For getting the string message use:
strerror(errno);
How to get error message when ifstream open fails
Every system call that fails update the errno
value.
Thus, you can have more information about what happens when a ifstream
open fails by using something like :
cerr << "Error: " << strerror(errno);
However, since every system call updates the global errno
value, you may have issues in a multithreaded application, if another system call triggers an error between the execution of the f.open
and use of errno
.
On system with POSIX standard:
errno is thread-local; setting it in one thread does not affect its
value in any other thread.
Edit (thanks to Arne Mertz and other people in the comments):
e.what()
seemed at first to be a more C++-idiomatically correct way of implementing this, however the string returned by this function is implementation-dependant and (at least in G++'s libstdc++) this string has no useful information about the reason behind the error...
In C++ std:: streams, after a failure, how to get a failure reason? Required: threadsafe and common to Windows and Linux (or at least Msvc/Gcc)
You can always throw your own exceptions using std::system_error
:
#include <cerrno>
#include <fstream>
#include <iostream>
#include <system_error>
int main()
{
try
{
std::ofstream foo{"/root/bar.baz"};
foo << "bla" << std::endl;
foo.close();
if(!foo)
throw std::system_error{errno, std::generic_category()};
}
catch(const std::system_error& err)
{
std::cout << "Error: " << err.code() << " - " << err.what() << std::endl;
}
return 0;
}
This returns Error: generic:13 - Permission denied
.
Why does std::ifstream not throw an exception even when exceptions are specifically enabled?
On failure, open()
sets failbit
, not badbit
. You are not asking the ifstream
to throwing an exception on failbit
.
Exception not caught opening a non-existing file using C++
It looks like a known bug in libstdc++.
The problem is that with the change to the C++11 ABI, many classes were duplicated in libstdc++6.so
, one version with the old ABI, other with the new one.
Exception classes were not duplicated so this problem didn't exist at the time. But then, in some newer revision of the language, it was decided that std::ios_base::failure
should derive from std::system_error
instead of std::exception
... but system_error
is a C++11 only class so it must use the new ABI flag or it will complain. Now you have two different std::ios_base::failure
classes and a mess in your hands!
The easy solution is to compile your program with -D_GLIBCXX_USE_CXX11_ABI=0
and resign to the old ABI until the bug is solved. Or alternatively, write catch (std::exception &e)
.
Related Topics
What Is the Purpose of a Declaration Like Int (X); or Int (X) = 10;
Forward Declaration with Vector of Class Type - Pointer to Incomplete Class Type Not Allowed
Is Using Unsigned Integer Overflow Good Practice
Lambdas and Capture by Reference Local Variables:Accessing After the Scope
What Is Aggregate Initialization
Inserting Elements in Multidimensional Vector
Gcc Can Compile a Variadic Template While Clang Cannot
How Can Cstring Be Passed to Format String %S
Why Use #Ifndef Class_H and #Define Class_H in .H File But Not in .Cpp
What Is a Good Naming Convention for Vars, Methods, etc in C++
How to Get a Non-Const C String Back from a C++ String
How Could Comma Separated Initialization Such as in Eigen Be Possibly Implemented in C++
Qt Moc with Implementations Inside of Header Files
Difference Between Regex_Match and Regex_Search
Does Boost::Bind() Copy Parameters by Reference or by Value
How to Include Data Object Files (Images, etc.) in Program and Access the Symbols