
David Abrahams wrote:
Tanguy Fautre <tanguy.fautre@spaceapplications.com> writes:
[...]
However, if a Python exception is thrown (and converted to the C++ exception boost::python::error_already_set), I get a segfault in the following function (m_ptr is null, hence the segfault):
inline api::object_base::~object_base() { Py_DECREF(m_ptr); }
This destructor is directly called at the end of the subsystem_script::register_events() function, leading me to believe that it is a temporary object being destructed.
Well, are you sure you're not doing something illegal somewhere? It's supposed to be an invariant that object (and object_base) never has a null m_ptr. That's why we're not using Py_XDECREF.
So, either Boost.Python is doing something to break that invariant, or some code (maybe yours, maybe mine) is incorrectly initializing that object, or there's a bug in the compiler's exception unwinding.
The funny thing is that if I do the following, then it works again.
void subsystem_script::register_events() { try { m_RegisterEvents(); }
catch (const error_already_set &) {
} }
However, doing a "throw;" in the catch to re-throw the exception does the same segfault. Converting the exception by throwing another object (e.g. std::runtime_error()) works.
I must admit that I'm totally puzzled.
Very strange. All I can say is what I always tell people: reduce your example to a _truly_ minimal one that reproduces the behavior (one C++ file and one python file) and either you'll discover what you did wrong or you'll give me enough to fix the problem. And please bring your Boost.Python questions to the C++-sig <http://boost.org/more/mailing_lists.htm#cplussig>.
After doing a minimal example reproducing this error, I think I found the problem. According to the C++ Programming Language (3rd ed), Section 14.7: "It is implementation-defined whether destructors are invoked when a program is terminated because of an uncaught exception.". That, I did not know. I thought destructor were always called. GCC 4.x and Visual C++ 2005 are indeed calling std::terminate without calling the destructors. Except... Except when debugging with VC++ 2005. When debugging, you have the choice to continue after a uncaught exception is thrown as if nothing happened. This effectively leads to a segfault as described as above. So it's not a problem with my application nor Boost.Python. Just my misunderstanding of uncaught exceptions and of Visual C++. Sorry I bothered you with this false alert. Tanguy