I tried the code from cppreference.com but it seems e.code() is not there:
#include <iostream>
#include <system_error> // std::make_error_condition, std::ios_errc
int main () {
std::cin.exceptions (std::ios::failbit|std::ios::badbit);
try {
std::cin.rdbuf(nullptr); // throws
} catch (std::ios::failure& e) {
std::cerr << "Fehler: ";
if (e.code() == // <<< ERROR: no e.code() ???
std::make_error_condition(std::io_errc::stream))
std::cerr << "stream\n";
else
std::cerr << "other\n";
}
}
My g++-6.2 and g++-5 and clang-3.9 (on linux) all say the same:
error: ‘class std::ios_base::failure’ has no member named ‘code’
if (e.code() == std::make_error_condition(std::io_errc::stream))
^~~~
Even the unchanged example does not compile for me
#include <iostream>
#include <fstream>
int main()
{
std::ifstream f("doesn't exist");
try {
f.exceptions(f.failbit);
} catch (const std::ios_base::failure& e)
{
std::cout << "Caught an ios_base::failure.\n"
<< "Explanatory string: " << e.what() << '\n'
<< "Error code: " << e.code() << '\n';
}
}
with
$ g++-6 etest.cpp -o etest.x
etest.cpp: In function ‘int main()’:
etest.cpp:12:42: error: ‘const class std::ios_base::failure’ has no member named ‘code’
<< "Error code: " << e.code() << '\n';
I tried g++-6, g++-5, adding -std=c++1y, -std=c++98, same result. (the latter is ok, though, I believe).
Which is really odd, because the online compiler on the site does compile it.
The single hint I have from a run with -E (preprocessor):
class ios_base
{
# 246 "/usr/include/c++/6/bits/ios_base.h" 3
public:
# 276 "/usr/include/c++/6/bits/ios_base.h" 3
class failure : public exception
{
public:
This looks as if failure does indeed not derive from system_error, which would explain why there is no code(). But why? Its plain Ubuntu g++, its g++-6, its C++14... I have no compiler tweaks, links, hacks...
There seems to be some use of
#if _GLIBCXX_USE_CXX11_ABI
in the vicinity. But does that interfere? If so, how to do I make it un-interfere?
Does anyone have any idea what might be going on here?
Related
I am writing a small application that modifies a text file. It first creates a copy of the file in case something goes wrong.
The following function creates this copy in the same directory. It takes the file's name as an argument and returns true if the copy is successfully created, and false if it fails.
#include <iostream>
#include <filesystem>
#include <fstream>
#include <string>
using std::ifstream;
using std::ofstream;
using std::string;
using std::cerr;
using std::cin;
using std::cout;
using std::endl;
bool backupFile(string FileName) {
cout << "Creating backup for " << FileName << "..." << endl;
try { // for debugging purposes
string NewName = "bkp_" + FileName;
string CurLine;
ifstream FileCopy(FileName);
ofstream FileBackup(NewName);
if (FileCopy.fail()) { // Could specify how file copy failed?
cerr << "Error opening file " << FileName << ".";
return false;
}
while (getline(FileCopy, CurLine)) { // Copy lines to new file
//cout << "Copying " << CurLine << "\" to " << NewName << "." << endl;
FileBackup << CurLine << "\n";
}
cout << "File successfully backed up to " << NewName << endl;
return true;
}
catch (const ifstream::failure& iE) {
cerr << "Exception thrown opening original file: " << iE.what() << endl;
return false;
}
catch (const ofstream::failure& oE) {
cerr << "Exception thrown outputting copy: " << oE.what() << endl;
}
catch (...) {
cerr << "Unknown exception thrown copying file." << endl;
return false;
}
}
I've used a few catch statements to indicate if there is an issue with the input (ifstream::failure), the output (ofstream::failure), or neither.
During compilation, however, the following error appears:
error C2312: 'const std::ios_base::failure &': is caught by 'const std::ios_base::failure &' on line 42
To me, the error implies that both ifstream::failure and ofstream::failure are caught on ifstream::failure, which seems strange. When I remove the catch for ofstream::failure, it runs fine.
Why is this the case?
ifstream::failure and ofstream::failure are both the same type defined in the std::ios_base base class std::ios_base::failure, you can't catch the same type in two separate catch clauses.
Note that neither of your streams will actually throw any exceptions, by default std::fstream doesn't throw any exceptions. You have to turn exceptions on by calling exceptions:
FileCopy.exceptions(f.failbit);
FileBackup.exceptions(f.failbit);
The above will cause an std::ios_base::failure to be thrown when the stream enters the failed state. As you are already checking for FileCopy.fail() you could just expand that checking to cover other failure cases (e.g. check that FileCopy doesn't fail during getline and that FileBackup also doesn't fail) rather than enabling exceptions.
For a legacy project I have to compile our code into a dylib with gcc which is then linked into a clang app starting with Intel-based macOS 10.15 (Catalina). I work with Big Sur 11.4 on a Mac Mini 2020 M1.
For testing purposes, I have created a small C++ project with header
foo.h
#pragma once
class Foo
{
public:
Foo();
virtual ~Foo();
void throw_runtime_error(const char* msg);
int bar(int a);
};
and code foo.cpp
#include <iostream>
#include <stdexcept>
#include "foo.h"
using namespace std;
Foo::Foo()
{
cout << "Foo:Foo() called" << endl;
}
Foo::~Foo()
{
cout << "Foo:~Foo() called" << endl;
}
void Foo::throw_runtime_error(const char* msg)
{
cout << "throwing runtime_error " << msg << endl;
throw runtime_error( msg );
}
int Foo::bar(int a)
{
cout << "Foo::bar(" << a << ") called" << endl;
return a + 1;
}
To create the dylib in a build subdir, I use the homebrewn g++ 10.2 with
g++-10 -arch x86_64 -fexceptions -dynamiclib -I../include ../src/foo.cpp -o ../bin/libMyDylib.dylib
For testing, how to be used along with clang 12.2.0 I have created a main.cpp in the bin subdir
#include "../include/foo.h"
#include <iostream>
#include <stdexcept>
int main()
{
Foo foo;
try
{
foo.throw_runtime_error("Hello you ugly little creatures!");
}
catch( const std::runtime_error &r )
{
std::cout << "Caught foo runtime_error, what = " << r.what() << std::endl;
}
catch( const std::exception &x )
{
std::cout << "Caught foo exception, what = " << x.what() << std::endl;
}
catch(...)
{
std::cout << "Caught foo exception, but without what()" << std::endl;
}
return foo.bar(42);
}
Now, if I use gcc-10 to compile main.cpp and link it with libMyDylib.dylib via g++-10 -arch x86_64 -L/Users/macos/bin -lMyDylib main.cpp -o main the exception handler in main.cpp catches the std::runtime_error properly.
If I use clang 12.2 along with g++ -arch x86_64 -L/Users/macos/bin -lMyDylib main.cpp -o main
then the output shows that only the catch (...) handler is triggered.
./main
Foo:Foo() called
throwing runtime_error Hello you ugly little creatures!
Caught foo exception, but without what()
Foo::bar(42) called
Foo:~Foo() called
So, can someone please give me a hint, what I am missing, in order to get 'cross-compiler' exceptions properly handled?
Thnxalot
I have tried to create a program in C++ that can catch and handle bad_alloc exception.
While writing the code, I have noticed no errors but when I have tried to compile this code I got C2276 error code and C3876 in Microsoft Visual Studio Community 2017.
The error itself seems to appear in the catch{...} code block.
#include "pch.h"
#include <iostream>
#include <string>
using namespace std;
class CanGoWrong {
public:
CanGoWrong() {
char *pMemory = new char[9999999999];
delete[] pMemory;
}
};
int main()
{
try {
CanGoWrong wrong;
}
catch(std::bad_alloc &e){
cout << "Caught exception: "<< e.what << e << endl;
}
cout << "Still running" << endl;
return 0;
}
The error with code C3867 ("non standart syntax, use &") I fixed this way :
from
cout << "Caught exception: "<< e.what << e << endl;
to:
cout << "Caught exception: "<< &e.what << e << endl;
Still, the error C2276 won't disappear. I guess there is something to do using basic std::exception class.
I want to understand how to do it right, this code is an course sample that I must follow and understand.
Boost version: 1.61, GCC version 6.2.0, C++14
Exceptions inside a boost::async() call seem to lose their type, while it works correctly with std::async. Is there a fundamental difference between std::async and boost::async I'm missing?
The following code works (using std::async):
#include <iostream>
#include <stdexcept>
#include <future>
using namespace std;
struct MyException : std::exception {
const char* what() const noexcept override { return "message"; }
};
int main() {
try {
auto future = std::async(std::launch::async, [] { throw MyException(); });
future.get();
} catch (const MyException& e) {
cout << "MyException caught. Message: " << e.what() << endl;
} catch (const std::exception& e) {
cout << "std::exception caught. Message: " << e.what() << endl;
}
}
and outputs
$ g++ test.cpp -std=c++14 -lpthread -lboost_thread -lboost_system && ./a.out
MyException caught. Message: message
However, the following code (it's the same, just using boost::async instead of std::async) does not work as expected:
#include <iostream>
#include <stdexcept>
#include <boost/thread/future.hpp>
using namespace std;
struct MyException : std::exception {
const char* what() const noexcept override { return "message"; }
};
int main() {
try {
auto future = boost::async(boost::launch::async, [] { throw MyException(); });
future.get();
} catch (const MyException& e) {
cout << "MyException caught. Message: " << e.what() << endl;
} catch (const std::exception& e) {
cout << "std::exception caught. Message: " << e.what() << endl;
}
}
It outputs:
$ g++ test.cpp -std=c++14 -lpthread -lboost_thread -lboost_system && ./a.out
std::exception caught. Message: std::exception
It also doesn't work for boost::future::then continuations:
#include <iostream>
#include <stdexcept>
#define BOOST_THREAD_VERSION 4
#include <boost/thread/future.hpp>
using namespace std;
struct MyException : std::exception {
const char* what() const noexcept override { return "message"; }
};
int main() {
try {
auto future = boost::make_ready_future(3).then([](boost::future<int>) -> int { throw MyException(); });
future.get();
} catch (const MyException& e) {
cout << "MyException caught. Message: " << e.what() << endl;
} catch (const std::exception& e) {
cout << "std::exception caught. Message: " << e.what() << endl;
}
}
outputs:
$ g++ test.cpp -std=c++14 -lpthread -lboost_thread -lboost_system && ./a.out
std::exception caught. Message: std::exception
So the concrete type of the exception seems to be lost when crossing the thread boundary. However, it doesn't seem to be connected to threading, because according to my tests, the same is true for std::launch::deferred (which works fine) and boost::launch::deferred (which loses the exception type).
I am currently catching errors from boost::filesystem::is_directory and showing the error to the user by calling "what()" on the exception. This gives the reason for failure but the error is strange to the user. For example:
boost::filesystem::is_directory: Access is denied
How can I catch the boost error and figure out what the actual cause is, so I can show a nicer error message?
By "nicer error message" would you mean something like
#include <iostream>
#include <boost/filesystem.hpp>
int main()
{
boost::filesystem::path p("/proc/1/fd/1");
try {
boost::filesystem::is_directory(p);
} catch(const boost::filesystem::filesystem_error& e)
{
if(e.code() == boost::system::errc::permission_denied)
std::cout << "Search permission is denied for one of the directories "
<< "in the path prefix of " << p << "\n";
else
std::cout << "is_directory(" << p << ") failed with "
<< e.code().message() << '\n';
}
}