Cannot catch exception from shared library in main.cpp - c++

I'm currently working on a game with a plugin based architecture. The executable consists mostly of a shared library loader and a couple of interface definitions. All the interesting stuff is happening in dynamic shared libraries which are loaded at start up.
One of the library classes throws an exception under certain circumstances. I would expect to be able to catch this exception and do useful stuff with it but this is where it gets weird. See following simplified example code:
main.cpp
int main()
{
try
{
Application app;
app.loadPlugin();
app.doStuffWithPlugin();
return 0;
}
catch(const std::exception& ex)
{
// Log exception
return 1;
}
}
Application.cpp
...
void doStuffWithPlugin()
{
plugin.doStuff();
}
...
Plugin.cpp
...
void doStuff()
{
throw exception_derived_from_runtime_error("Something is wrong");
}
...
Plugin.cpp exists in a dynamic shared library which is successfully loaded and which has afterwards created an object of class Plugin. The exception_derived_from_runtime_error is defined in the application. There is no throw() or noexcept.
I would expect to catch the exception_derived_from_runtime_error in main but that doesn't happen. Compiled with GCC 4.8 using C++11 the application crashes with This application has requested the Runtime to terminate it in an unusual way..
I replaced catch(const std::exception& ex) with catch(...) but that didn't make any difference. The weird part is if i catch the exception in doStuffWithPlugin() it works. If i rethrow it using throw; it fails again but it can be caught if i use throw ex;:
Application.cpp
void doStuffWithPlugin()
{
try
{
plugin.doStuff();
}
catch(const exception_derived_from_runtime_error& ex)
{
// throw; <- Not caught in main().
// throw ex; <- Caught in main().
}
}
Hopefully somebody has an idea. Thanks for every help you can give.

As mentioned in the comments this seems to be a problem with shared libraries on Windows. The behavior occurs if the library is unloaded and an object created in this libraries remains in memory. The application seems to crash immediately. The only reference to this problems are found if gcc as an cross compiler or MinGW is used. See also https://www.sourceware.org/ml/crossgcc/2005-01/msg00022.html

Related

How to catch SEH thrown from ntdll.dll's TppRaiseInvalidParameter?

I am using MSVC2019 and COM and compiling using /EHa
getting a SEH from ntdll.dll from TppRaiseInvalidParameter that I am trying to catch but seem unable to. I know exactly why the exception is thrown, but that is not the issue here.
I tried using all the mechanisms described in the MSDN docs (__try/__except, _set_se_translator, SetUnhandledExceptionFilter), but none seem to trigger in this case.
I also tried raising exceptions using RaiseException and RtlRaiseException (used by TppRaiseInvalidParameter) and those seem to be caught no problem in the __except handler.
The only thing I've been able to spot in TppRaiseInvalidParameter is that it calls __SEH_prolog4_GS at the beginning, but from what I've read that is normal code generated by the compiler for SEHs, but I'm new to SEHs in general.
My questions are: why can't I catch that exception? Is there any way to catch it?
Minimal code for reproduction
extern "C"
{
void (WINAPI* TppRaiseInvalidParameter)();
}
void func()
{
__try
{
HMODULE ntdll;
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, "ntdll.dll", &ntdll);
TppRaiseInvalidParameter = reinterpret_cast<decltype(TppRaiseInvalidParameter)>((LONG)ntdll + 0x104EBDL); // it's not an exported function and your offset may be different
TppRaiseInvalidParameter();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
puts("exception caught");
}
}

C++ bit7z : Exception thrown at ... in ... Microsoft C++ exception: bit7z::BitException at memory location 0x001AF440 & paths of directory and files

I'm trying to create a program that, on execution, zips a given directory. Most of my errors have been resolved and I am hopefully getting to the end of this, but I still have the issue of an exception being thrown and a question regarding the program. I code in C++20 and on Visual Studio 2019.
I've come across this exact error when debugging the program:
Exception thrown at 0x76820B42 in aixLogger.exe: Microsoft C++ exception: bit7z::BitException at memory location 0x001AF440.
I already checked with a breakpoint what code is giving me this error:
catch (const BitException& ex) {
ex.what(); //<-
}
The code runs otherwise and isn't giving me any error messages, the breakpoint activates on the line I marked with an arrow (not actually part of my code).
To eliminate further possible edits I will add the rest of my code as well:
main.cpp
#include <QCoreApplication>
#include <string>
#include <iostream>
#include <filesystem>
#include <bit7z.hpp>
#include "main.h"
#include <bitcompressor.hpp>
namespace fs = std::filesystem;
using namespace bit7z;
using namespace std;
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
try {
Bit7zLibrary lib{ L"7z.dll" };
BitCompressor compressor{ lib, BitFormat::Zip };
//vector< wstring > files = { L"aretz/Downloads/test" };
wstring dir = { L"D: / local / aretz / Programmierung / git - workplace / aixLogger / test /" } ;
wstring zip = { L"zippedtest.zip" };
compressor.compressDirectory(dir, zip);
}
catch (const BitException& ex) {
ex.what();
}
return a.exec();
}
void AIXLogger::CompressDir() {
/*try {
Bit7zLibrary lib{ L"7z.dll" };
BitCompressor compressor{ lib, BitFormat::Zip };
vector< wstring > files = { L"C:/Users/aretz/Downloads/test" };
wstring zip = { L"zippedtest.zip" };
compressor.compressFiles(files, zip);
}
catch (const BitException& ex) {
ex;
}*/
}
main.h
#pragma once
#include <qwidget.h>
#include <qobject.h>
#include <bit7z.hpp>
class AIXLogger : public QWidget
{
Q_OBJECT
public slots:
public:
void CompressDir();
};
I've currently commented out the function CompressDir() as I can't call it in my main since it gives me either a syntax error or tells me the identifier is undefined.
Syntax Error:
AIXLogger.CompressDir(); the dot is marked as the error
identifier is undefined:
CompressDir();
I don't know what exactly is causing the catch to thrown an exception. From other posts I suspected that my paths for the files and directories are at fault, but changing them or moving my test directory didn't help at all. Removing the try and catch lines from my codeblock only adds the same error message where Exception Thrown is being replaced by Unhandled Exception. Thanks to anyone who can help.
I already checked with a breakpoint what code is giving me this error:
catch (const BitException& ex) {
ex.what(); //<-
}
The code runs otherwise and isn't giving me any error messages
The code isn't giving you any error message since you're not doing anything with the information provided by the thrown exception.
You're simply calling ex.what() without, for example, printing the error message string it returns, e.g., via std::cout.
the breakpoint activates on the line I marked with an arrow (not actually
part of my code).
I don't know what exactly is causing the catch to thrown an exception. From other posts I suspected that my paths for the files and directories are at fault, but changing them or moving my test directory didn't help at all.
The ex.what() error message should give you more details about the actual issue you're having.
By the way, I'm the author of the bit7z library, and from my experience and looking at the code you posted, I can think of some possible causes (the most common ones):
The program could not find the 7z.dll library.
Please ensure that the DLL is in the same directory as the executable or in one of the default DLL search paths of Windows.
The program could not find the directory path to be compressed.
As before, make sure that the path exists.

'runtime_error' from c++ not captured in iOS

In my iOS project, I use a C++ module. The C++ module throws exception for some cases and the Objective C++ wrapper fails to catch it. For instance
Here is my HelloWorld.h
#include <string>
using namespace std;
class HelloWorld{
public:
string helloWorld();
};
#endif
Implementation HelloWorld.cpp
#include "HelloWorld.h"
string HelloWorld::helloWorld(){
throw (std::runtime_error("runtime_error")); // Throwing exception to test
string s("Hello from CPP");
return s;
}
Objective C++ wrapper HelloWorldIOSWrapper.h
#import <Foundation/Foundation.h>
#interface HelloWorldIOSWrapper:NSObject
- (NSString*)getHello;
#end
#endif /* HelloWorldIOSWrapper_h */
Implementation HelloWorldIOSWrapper.mm
#import "HelloWorldIOSWrapper.h"
#include "HelloWorld.h"
#implementation HelloWorldIOSWrapper
- (NSString*)getHello{
try {
HelloWorld h;
NSString *text=[NSString stringWithUTF8String: h.helloWorld().c_str()];
return text;
} catch (const std::exception & e) {
NSLog(#"Error %s", e.what());
}
return nil;
}
#end
#import "HelloWorldIOSWrapper.h" is added to the Bridging-Header
And now, when I try to invoke getHello() from controller, app crashes leaving the below message in log
libc++abi: terminating with uncaught exception of type std::runtime_error: runtime_error
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
terminating with uncaught exception of type std::runtime_error: runtime_error
I expect that the exception must be caught in the wrapper, but, no idea why is it not caught leading to app crash. What do I miss?
C++ Interoperability
In 64-bit processes, Objective-C exceptions (NSException) and C++
exception are interoperable. Specifically, C++ destructors and
Objective-C #finally blocks are honored when the exception mechanism
unwinds an exception. In addition, default catch clauses—that is,
catch(...) and #catch(...)—can catch and rethrow any exception
On the other hand, an Objective-C catch clause taking a dynamically
typed exception object (#catch(id exception)) can catch any
Objective-C exception, but cannot catch any C++ exceptions. So, for
interoperability, use #catch(...) to catch every exception and #throw;
to rethrow caught exceptions. In 32-bit, #catch(...) has the same
effect as #catch(id exception).
#try {
}
#catch (...) {
}

C++ Exceptions and Static Linking

I'm trying to use exceptions in a C++ code that runs on raspberry-pi zero.
When I link the code dynamically it works fine.
However, when I link it statically, I get:
terminate called after throwing an instance of 'std::exception'
terminate called recursively
Aborted
An example code to reproduce the problem:
#include <exception>
#include <stdio.h>
void foo(void)
{
throw std::exception();
}
int main (void)
{
try
{
foo();
}
catch(...)
{
printf("caught an exception\n");
}
return (0);
}
My "problematic" link command is:
g++ exceptionTest.cpp -o exceptionTest.out --static
Why does the static linking disrupts the exceptions mechanism?
Is there something I could do in my link command (e.g. add flags) to fix this?
Note: my problem appears very similar to
GCC arm-none-eabi (Codesourcery) and C++ Exceptions
but the OP there worked on a different system and the suggested solution was related to a link script (which I don't use).

How can MSVC6 handle exceptions from extern "C" functions?

I'm working on an application written in Visual Studio 6 (I know, FML) that is calling functions in a DLL using LoadLibrary and GetProcAddress. The newer code can't compile in VC6, and needs a newer compiler. The DLL has a few functions that construct a C++ object, and then the VC6 program uses the object through an abstract class.
This works just fine usually, but it runs into problems when the functions retrieved by GetProcAddress throw exceptions -- even when the exceptions are caught within the DLL. I've noticed that this doesn't happen when the abstract class's methods throw an exception. Things work normally in that case.
What am I doing wrong here? How can I make VC6 generate code to handle the exceptions properly?
Edit: Here's an example of a function that causes the program to crash:
extern "C" __declspec(dllexport) Box* getBox(const char* addr)
{
try {
return createBox(addr);
} catch (std::exception& ex) {
LOG_ERROR("Open failed: " << ex.what());
return 0;
} catch (...) {
LOG_ERROR("Error while opening.");
return 0;
}
}
You cannot do inheritance cross compiler versions like that. It almost works but exceptions and a few other things go crazy.