I have this method in library:
#include <stdexcept>
mytype* myfunc()
{
throw std::runtime_error("is uncatchable");
}
and this in int main() of executable process which links library.
try { myfunc(); }
catch(std::exception const& ex) { std::cout << "handled: " << ex.what() << std::endl; }
catch(...) { std::cout << "something else..." << std::endl; }
And that is the output:
terminate called after throwing an instance of 'std::runtime_error'
what(): is uncatchable
Abort (core dumped)
Question:
Why exception was not catch?
I'm not managing my compiler's flags (icc-11.X), also OS is also not under my control.
List of compiler flags:
-DLINUX -DLINUX_X64 -DGNU_SOURCE -fPIC -Wcheck -Wshadow -Wdeprecated -Wreturn-type -Wcomment -Wmissing-prototypes -Wp64 -Drcsid="__attribute__((used)) rcsid"
-D__EXTENSIONS__ -D__STD_C__ -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -DNDEBUG
__EXCEPTIONS is defined.
May there exist settings for Linux which lead to this?
May there exist settings for compiler which lead to this?
Related
Suppose I have a function in a shared library throwing some object, and a main executable calling that function and attempting to catch that object, e.g.
decl.h
#ifndef DECL_H
#define DECL_H
void pitch();
struct MyException {
MyException();
MyException(const MyException&);
~MyException();
};
#endif
pitch.cpp
#include "decl.h"
MyException::MyException() {}
MyException::MyException(const MyException&) {}
MyException::~MyException() {}
void pitch() {
throw MyException();
}
main.cpp
#include <stdio.h>
#include "decl.h"
int main() {
try { pitch(); }
catch (MyException& e) { printf("MyException()\n"); }
catch (...) { printf("[unknown exception]\n"); }
}
Makefile
all:
$(CXX) -shared -fPIC $(CXXFLAGS) $(LTO) pitch.cpp -o libpitch.so
$(CXX) -g $(CXXFLAGS) $(LTO) main.cpp -L. -lpitch
./a.out
If I compile without link-time optimization, all is well:
CXXFLAGS="-g -O2" LTO="" make
c++ -shared -fPIC -g -O2 pitch.cpp -o libpitch.so
c++ -g -g -O2 main.cpp -L. -lpitch
./a.out
MyException()
But once I turn on link-time optimization, the thrown object is no longer caught:
CXXFLAGS="-g -O2" LTO="-flto" make
c++ -shared -fPIC -g -O2 -flto pitch.cpp -o libpitch.so
c++ -g -g -O2 -flto main.cpp -L. -lpitch
./a.out
[unknown exception]
Is this expected behavior? Is this a problem in my C++ code, or something else? This is on macOS 10.14.5:
$ c++ -v
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
This is not expected behavior.
I tested it on linux (ubuntu) with gcc 4.x, 5.x, 6.x, 7.x and 8.x and with clang 6.0. All work just fine with -O2 -flto.
Unfortunately, since I cannot reproduce it (I don't have a Mac) I can't tell you what is wrong, but it isn't your code imho.
EDIT:
I can't in good conscious say there is "nothing wrong" with your code (although I tested it as shown by you - HOWEVER, I needed to set LD_LIBRARY_PATH="." for ./a.out to work (so perhaps you are loading some other library?)) without showing you how I'd write the above code:
//decl.h:
#pragma once
#include <exception>
void pitch();
struct MyException : public std::exception
{
};
//pitch.cpp:
#include "decl.h"
void pitch()
{
throw MyException();
}
// main.cpp:
#include "decl.h"
#include <iostream>
int main()
{
try
{
pitch();
}
catch (MyException const& e)
{
std::cout << "MyException(): " << e.what() << std::endl;
}
catch (...)
{
std::cerr << "[unknown exception]" << std::endl;
}
}
This code, compiles with g++ using -std=c++11. Linking with g++, when libunwind is linked in statically program crashes after catching in exerciseBug (after rethrow).
LDFLAGS that result in crash:
-Wl,-Bstatic -lunwind -Wl,-Bdynamic -llzma
when libunwind is linked in dynamically, code works as normally. LDFLAGS that result in normal operation:
-Wl,-Bstatic -Wl,-Bdynamic -lunwind -llzma
#include <iostream>
using namespace std;
void exerciseBug()
{
try {
throw exception();
} catch (exception &err) {
cerr << "caught in exerciseBug\n";
throw;
}
}
int main()
{
try {
exerciseBug();
} catch (exception &err) {
cerr << "caught in main\n";
::exit(0);
}
}
Question is why is does libunwind need to be dynamically linked in?
(Running on Ubuntu 16.04; g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609)
After narrowing down everything I see that when I include boost/asio/write.hpp, the exception wont be caught and the application terminates on windows (This app. has requested to terminate...)
However, when I comment just this include line, the exception works perfectly.
#include <stdexcept>
#include <iostream>
#include <boost/asio/write.hpp>
int main() {
try {
throw std::logic_error("aajj");
} catch (std::exception &e) {
std::cout << "Caught:" << e.what() << std::endl;
}
}
invoked build using these gcc settings
g++ -D_WIN32_WINNT=0x0601 -O0 -g3 -Wall -c -fmessage-length=0 -o "tests\\so_main.o" "..\\tests\\so_main.cpp"
g++ -static-libgcc -static-libstdc++ -Xlinker --enable-auto-import -o client.exe "tests\\so_main.o" -lboost_system-mgw45-mt-1_55 -lws2_32
I am trying to compile simple code with -fno-exceptions flag. Its giving error.
Please let me know how to suppress this. I am using gcc version 4.6.3
Code
#include <iostream>
using namespace std;
int main () {
try
{
throw 20;
}
catch (int e)
{
cout << "An exception occurred. Exception Nr. " << e << '\n';
}
return 0;
}
Log
> g++ throw.cc -o out -fno-exceptions
throw.cc: In function ‘int main()’:
throw.cc:10:11: error: exception handling disabled, use -fexceptions to enable
throw.cc:14:56: error: ‘e’ was not declared in this scope
Edit
I have a client code which have lot throws like this. I have to integrate this in my project and I can't control compilation flags to build(which will come from config which has -fno-exceptions enabled). I wanted a quick work around that I can suggest.
EDIT
I found a workaround see below for my answer.
You cannot use -fno-exceptions flag with program, that use exceptions (try/catch/throw).
Quote from gcc manual
Before detailing the library support for -fno-exceptions, first a
passing note on the things lost when this flag is used: it will break
exceptions trying to pass through code compiled with -fno-exceptions
whether or not that code has any try or catch constructs. If you might
have some code that throws, you shouldn't use -fno-exceptions. If you
have some code that uses try or catch, you shouldn't use
-fno-exceptions.
You can't compile a program with this flag if you throw exceptions in your own code. The -fno-exceptions flag does the following:
All exception handling in STL libraries are removed; throws are replaced with abort() calls
Stack unwind data and code is removed. This saves some code space, and may make register allocation marginally easier for the compiler (but I doubt it'll have much performance impact). Notably, however, if an exception is thrown, and the library tries to unwind through -fno-exceptions code, it will abort at that point, as there is no unwind data.
This will, effectively, turn all exceptions into abort()s, as you would like. Note, however, that you will not be allowed to throw - any actual throws or catchs in your code will result in a compile-time error.
I found a workaround. Except for the "e" in the catch block the code can be rewritten like
#include <iostream>
using namespace std;
int main () {
__try
{
__throw_exception_again 20;
}
__catch (int e)
{
cout << "An exception occurred." << '\n';
}
return 0;
}
and can be compiled with
g++ throw.cc -o out -fno-exceptions.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 years ago.
I am having a problem calling functions from my test_dll.dll in an outside c++ main. Working on eclipse cdt luna sr2 64, Windows 7. Using the MinGW toolchain for compilation.
The dll .cpp code :
#include <iostream>
#include "MyClass.h"
namespace myNamespace {
MyClass::MyClass() :a(1) {
std::cout << "MyClass():a(" << this->a << ")"<<std::endl;
}
MyClass::~MyClass() { }
void myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}
}
and it is compiled within eclipse with the following lines :
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o MyClass.o "..\\MyClass.cpp"
g++ -shared -o libtest_dll.dll MyClass.o
My main code is the following :
#include <iostream>
#include "MyClass.h"
using namespace std;
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
myNamespace::MyClass *instance = new myNamespace::MyClass;
instance->myFunc();
return 0;
}
and it is compiled with the following
g++ "-IC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll" "-includeC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll\\MyClass.h" -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\test_main.o" "..\\src\\test_main.cpp"
g++ "-LC:\\Users\\nxa02192\\Desktop\\MY_WORKSPACE\\test_dll\\Debug" -o test_main.exe "src\\test_main.o" -llibtest_dll
src\test_main.o: In function `main':
C:\Users\nxa02192\Desktop\MY_WORKSPACE\test_main\Debug/../src/test_main.cpp:20: undefined reference to `myNamespace::MyClass::myFunc()'
collect2.exe: error: ld returned 1 exit status
However, what i don't get is that if i just instanciate the class, it will output the correct a=1 value, as specified in the constructor.
I already specified the include paths to the compiler and the library path and file to the linker, as you can see in the compiling commands. Any Ideas ? Thanks !
Change
void myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}
to
void MyClass::myFunc() {
std::cout << "myFunc() has been called !" << std::endl;
}