$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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