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");
}
}
I export a function from d to c++ with extern(C++). The d code has a try catch statement on the highest level.Whenever the d code throws a exception the program aborts. I have c++ objects on the call stack and call the function in d. Then there is the d try catch statement and then the d exception throw.
The d code:
extern (C++) void ThrowEx() {
try {
throw new Exception("hello");
} catch (Exception ex) {
}
}
The c++ code:
extern "C" int rt_init();
void ThrowEx();
void func() {
rt_init();
ThrowEx();
}
When I change ThrowEx to not throw an exception everything works as expected. The d code gets executed and no error occurs.
When the program crashes the following output is generated:
dwarfeh(224) fatal error
uncaught exception
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
Situation
I want to create a Python language binding for a C++ API using SWIG. Some of the API functions may throw exceptions. The C++ application has a hierarchy of self-defined exceptions, like this example:
std::exception
-> API::Exception
-> API::NetworkException
-> API::TimeoutException
-> API::UnreachableException
-> API::InvalidAddressException
The desired behavior is as follows:
All exception types should have a matching Python class as wrapper. These wrapper classes should be valid Python exceptions.
When an API call throws a C++ exception, it should be caught. The corresponding Python exception (i.e. the wrapper class of the caught C++ exception) should be thrown.
This should be a dynamic process: the Python exception type is decided at runtime, only based on the runtime type of the caught C++ exception. This way, there is no need to describe the complete exception hierarchy in the SWIG interface file.
Problems and questions
Wrapper classes are no Python exceptions.
While SWIG creates wrapper classes for all self-defined exceptions (like for any other class), these classes are not Python exceptions. The wrapper of the base exception (API::Exception in the example) extends Object instead of BaseException, the Python class of which all exceptions in Python should be derived.
Furthermore, it doesn't seem possible to let SWIG add a parent class manually. Note this is possible when using SWIG with Java through the usage of %typemap(javabase) (see SWIG documentation for details).
How can the Python C API throw a user-defined exception?
The most common way to throw a Python exception from the Python C API is by calling PyErr_SetString [reference]. This is also shown in the demo application below.
But this is only trivial with the standard (built-in) exceptions of Python, because references to them are stored in global variables [reference] in the Python C API.
I know there is a method PyErr_NewException [reference] to get references to self-defined exceptions, but I didn't got this working.
How can the Python C API evaluate the C++ type at runtime and then find the corresponding Python wrapper class by name?
I assume a Python class can be searched by name at runtime, through the reflection part of the Python C API. Is this the way to go? And how is it done in practice?
Demo application
To experiment with this problem, I created a tiny C++ API with a single function that calculates the factorial of a number. It has a minimal self-defined exception hierarchy, consisting of only one class TooBigException.
Note this exception acts as the base exception in the general problem and the application should work with any subclass of it. This means the solution may only use the dynamic (i.e. runtime) type of the caught exception to rethrow it in Python (see below).
The full source code of the demo application is as follows:
// File: numbers.h
namespace numbers {
int fact(int n);
}
// File: numbers.cpp
#include "TooBigException.h"
namespace numbers {
int fact(int n) {
if (n > 10) throw TooBigException("Value too big", n);
else if (n <= 1) return 1;
else return n*fact(n-1);
}
}
// File: TooBigException.h
namespace numbers {
class TooBigException: public std::exception {
public:
explicit TooBigException(const std::string & inMessage,
const int inValue);
virtual ~TooBigException() throw() {}
virtual const char* what() const throw();
const std::string & message() const;
const int value() const;
private:
std::string mMessage;
int mValue;
};
}
// File: TooBigException.cpp
#include "TooBigException.h"
namespace numbers {
TooBigException::TooBigException(const std::string & inMessage, const int inValue):
std::exception(),
mMessage(inMessage),
mValue(inValue)
{
}
const char* TooBigException::what() const throw(){
return mMessage.c_str();
}
const std::string & TooBigException::message() const {
return mMessage;
}
const int TooBigException::value() const {
return mValue;
}
}
To get the Python binding I use the following SWIG interface file:
// File: numbers.i
%module numbers
%include "stl.i"
%include "exception.i"
%{
#define SWIG_FILE_WITH_INIT
#include "TooBigException.h"
#include "numbers.h"
%}
%exception {
try {
$action
}
catch (const numbers::TooBigException & e) {
// This catches any self-defined exception in the exception hierarchy,
// because they all derive from this base class.
<TODO>
}
catch (const std::exception & e)
{
SWIG_exception(SWIG_RuntimeError, (std::string("C++ std::exception: ") + e.what()).c_str());
}
catch (...)
{
SWIG_exception(SWIG_UnknownError, "C++ anonymous exception");
}
}
%include "TooBigException.h"
%include "numbers.h"
So every call to the API is wrapped by a try-catch block. First exceptions of our base type are caught and handled. Then all other exceptions are caught and rethrown using the SWIG exception library.
Note any subclass of numbers::TooBigException is caught and the wrappers of their dynamic (i.e. runtime) type should be thrown, not the wrapper of their static (i.e. compile time) type, which is always TooBigException!
The project can be built easily by executing the following commands on a Linux machine:
$ swig -c++ -python numbers.i
$ g++ -fPIC -shared TooBigException.cpp numbers.cpp numbers_wrap.cxx \
-I/usr/include/python2.7 -o _numbers.so
Current implementation
My current implementation still (successfully) throws a fixed standard Python exception. The code <TODO> above is then replaced by:
PyErr_SetString(PyExc_Exception, (std::string("C++ self-defined exception ") + e.what()).c_str());
return NULL;
Which gives the following (expected) behavior in Python:
>>> import numbers
>>> fact(11)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception: C++ self-defined exception Value too big
It looks like someone has answered your basic question over on the swig-user list...
%exception {
try {
$action
} catch (MyException &_e) {
SWIG_Python_Raise(SWIG_NewPointerObj(
(new MyException(static_cast<const MyException& >(_e))),
SWIGTYPE_p_MyException,SWIG_POINTER_OWN),
"MyException", SWIGTYPE_p_MyException);
SWIG_fail;
}
}
This does assume you have generated wrappers for your exception classes, I believe.
Example for your hierarchy
std::exception
-> API::Exception
-> API::NetworkException
-> API::TimeoutException
-> API::UnreachableException
-> API::InvalidAddressException
example.i:
%module example
%include "stl.i"
%include "exception.i"
%{
#define SWIG_FILE_WITH_INIT
#include "example.cpp"
%}
%{
#define CATCH_PE(Namespace,Exception) \
catch(const Namespace::Exception &e) \
{ \
SWIG_Python_Raise(SWIG_NewPointerObj(new Namespace::Exception(e), \
SWIGTYPE_p_##Namespace##__##Exception,SWIG_POINTER_OWN), \
#Exception, SWIGTYPE_p_##Namespace##__##Exception); \
SWIG_fail; \
} \
/**/
// should be in "derived first" order
#define FOR_EACH_EXCEPTION(ACTION) \
ACTION(API,UnreachableException) \
ACTION(API,TimeoutException) \
ACTION(API,InvalidAddressException) \
ACTION(API,NetworkException) \
ACTION(API,Exception) \
/**/
// In order to remove macros, need traits:
// http://swig.10945.n7.nabble.com/traits-based-access-to-swig-type-info-td12315.html
%}
%exception {
try {
$action
}
FOR_EACH_EXCEPTION(CATCH_PE)
catch (const std::exception & e)
{
SWIG_exception(SWIG_RuntimeError, (std::string("C++ std::exception: ") + e.what()).c_str());
}
catch (...)
{
SWIG_exception(SWIG_UnknownError, "C++ anonymous exception");
}
}
%include "example.cpp"
example.cpp:
#include <exception>
#include <stdexcept>
namespace API
{
struct Exception: std::exception
{
virtual const char* what() const throw()
{
return "It is API::Exception";
}
};
struct NetworkException: Exception
{
virtual const char* what() const throw()
{
return "It is API::NetworkException";
}
};
struct TimeoutException: NetworkException
{
virtual const char* what() const throw()
{
return "It is API::TimeoutException";
}
};
struct UnreachableException: NetworkException
{
virtual const char* what() const throw()
{
return "It is API::UnreachableException";
}
};
struct InvalidAddressException: Exception
{
virtual const char* what() const throw()
{
return "It is API::InvalidAddressException";
}
};
inline void select(int i)
{
switch(i)
{
case 0: throw Exception();
case 1: throw NetworkException();
case 2: throw TimeoutException();
case 3: throw UnreachableException();
case 4: throw InvalidAddressException();
default: throw std::runtime_error("It is std::runtime_error");
}
}
}
Build:
swig -c++ -python example.i &&
g++ -fPIC -shared -lpython2.7 example.cpp example_wrap.cxx -I/usr/include/python2.7 -o _example.so
test.py:
#!/usr/bin/env python2.7
from exceptions import BaseException
from example import *
def catch(i):
try:
select(i)
except UnreachableException as e:
print "Caught UnreachableException"
print e.what()
print e
except TimeoutException as e:
print "Caught TimeoutException"
print e.what()
print e
except InvalidAddressException as e:
print "Caught InvalidAddressException"
print e.what()
print e
except NetworkException as e:
print "Caught NetworkException"
print e.what()
print e
except Exception as e:
print "Caught Exception"
print e.what()
print e
except BaseException as e:
print "Caught BaseException"
print str(e)
print "_"*16
for i in xrange(6):
catch(i)
Output is:
Caught Exception
It is API::Exception
<example.Exception; proxy of <Swig Object of type 'API::Exception *' at 0x7f9f54a02120> >
________________
Caught NetworkException
It is API::NetworkException
<example.NetworkException; proxy of <Swig Object of type 'API::NetworkException *' at 0x7f9f54a02120> >
________________
Caught TimeoutException
It is API::TimeoutException
<example.TimeoutException; proxy of <Swig Object of type 'API::TimeoutException *' at 0x7f9f54a02120> >
________________
Caught UnreachableException
It is API::UnreachableException
<example.UnreachableException; proxy of <Swig Object of type 'API::UnreachableException *' at 0x7f9f54a02120> >
________________
Caught InvalidAddressException
It is API::InvalidAddressException
<example.InvalidAddressException; proxy of <Swig Object of type 'API::InvalidAddressException *' at 0x7f9f54a02120> >
________________
Caught BaseException
C++ std::exception: It is std::runtime_error
________________
Based on answer in maillist.
I'm trying to play with handling unexpected exceptions, but cannot make it to work. This is example from: C++ Reference
// set_unexpected example
#include <iostream>
#include <exception>
using namespace std;
void myunexpected () {
cerr << "unexpected called\n";
throw 0; // throws int (in exception-specification)
}
void myfunction () throw (int) {
throw 'x'; // throws char (not in exception-specification)
}
int main (void) {
set_unexpected (myunexpected);
try {
myfunction();
}
catch (int) { cerr << "caught int\n"; }
catch (...) { cerr << "caught other exception (non-compliant compiler?)\n"; }
return 0;
}
They say that output should be:
Output:
unexpected called
caught int
Which doesn't happen when I try it. My output is:
caught other exception (non-compliant compiler?)
I'm using VS2010 sp1
Documentation of unexpected says:
The C++ Standard requires that unexpected is called when a function throws an exception that is not on its throw list. The current implementation does not support this.
So the answer is that VC10 is a non-compliant compiler.
Visual Studio does not implement the standard correctly. See this MSDN page. The int is parsed, but not used.
Visual C++ always issues Warning C4290 when function has exception specifiers. From the same article in MSDN: "A function is declared using exception specification, which Visual C++ accepts but does not implement." So, this compiler does not comply with standard.