Boost logo

Boost :

From: Tanguy Fautre (tanguy.fautre_at_[hidden])
Date: 2006-08-31 06:23:11


David Abrahams wrote:
> Tanguy Fautre <tanguy.fautre_at_[hidden]> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk