Re: [sigc] SEGV while using libsigc++ in an apparently legit way
- From: Murray Cumming <murrayc murrayc com>
- To: Régis Duchesne <hpreg vmware com>
- Cc: libsigc++ list <libsigc-list gnome org>
- Subject: Re: [sigc] SEGV while using libsigc++ in an apparently legit way
- Date: Fri, 04 Mar 2005 16:41:24 +0100
On Thu, 2005-03-03 at 11:40 -0800, R�s Duchesne wrote:
> Folks,
>
> I'm reporting this issue both to the GCC people and the libsigc++
> people, because the issue could be in either of them or both. On the
> surface, it looks like a g++ issue, but when you look deeper, libsigc++
> might be relying on a behavior that is unspecified by any C++ standard.
>
> Input
> -----
> File test1.cc is attached.
A simplified test case is attached. It does not need 3 base classes to
crash.
However, we'd rather have a libsigc++-only test case rather than one
that uses gtkmm too, and the g++ developers would want one that did not
involve even libsigc++.
> Command line
> ------------
> g++ -v -save-temps -O -g `pkg-config --cflags --libs gtkmm-2.4` test1.cc
> -o test1
I left out the "-v -save-temps -O -g". They aren't necessary to make it
crash.
[snip]
> o Binary output
> When running the binary, a window pops up on the screen. In that window,
> there is a button. Click on the button. The binary gets a SEGV. This is
> the issue.
>
> Why it could be a g++ issue
> ---------------------------
> If you remove -O from the command line, then the binary does not get a
> SEGV, which is the expected behavior.
It segfaults for me, on Fedora Core 3,
[murrayc murrayclaptop ~]$ g++ --version
g++ (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)
The valgrind output is attached, from after pressing the Discard button.
I used
valgrind --tool=memcheck --num-callers=20 ./a.out
> Why it could be a libsigc++ issue
> ---------------------------------
> o Here is the relevant backtrace at the time of the SEGV
>
> #0 0x406730f2 in sigc::trackable::callback_list ()
> from /usr/lib/libsigc-2.0.so.0
> #1 0x4067306f in sigc::trackable::remove_destroy_notify_callback ()
> from /usr/lib/libsigc-2.0.so.0
> #2 0x0804d253 in
> sigc::visit_each<sigc::internal::limit_derived_target<sigc::trackable*,
> sigc::internal::slot_do_unbind>, Dlg> (_A_action= 0xbfffcd04,
> _A_functor= 0x100e3740) at slot_base.h:166
> #3 0x0804d216 in
> sigc::visit_each<sigc::internal::limit_derived_target<sigc::trackable*,
> sigc::internal::slot_do_unbind>, void, Dlg> (_A_action= 0xbfffcd04,
> _A_target= 0x100e3740) at mem_fun.h:1798
> #4 0x0804d1df in
> sigc::visit_each<sigc::internal::limit_derived_target<sigc::trackable*,
> sigc::internal::slot_do_unbind>, sigc::bound_mem_functor0<void, Dlg> >
> (_A_action= 0xbfffcd04, _A_target= 0x80a6998) at adaptor_trait.h:264
> #5 0x0804cec0 in sigc::visit_each_type<sigc::trackable*,
> sigc::internal::slot_do_unbind,
> sigc::adaptor_functor<sigc::bound_mem_functor0<void, Dlg> > > (
> _A_action= 0x100e3740, _A_functor= 0x80a6998) at visit_each.h:124
> #6 0x0804ce9d in
> sigc::internal::typed_slot_rep<sigc::bound_mem_functor0<void, Dlg>
> >::destroy (data=0x100e3740) at slot_base.h:160
> #7 0x40673a45 in sigc::internal::slot_rep::notify ()
> from /usr/lib/libsigc-2.0.so.0
> #8 0x4067323b in
> sigc::internal::trackable_callback_list::~trackable_callback_list ()
> from /usr/lib/libsigc-2.0.so.0
> #9 0x406730ce in sigc::trackable::notify_callbacks ()
> from /usr/lib/libsigc-2.0.so.0
> #10 0x40672fcf in sigc::trackable::~trackable () from
> /usr/lib/libsigc-2.0.so.0
> #11 0x0804d0b6 in ~Dlg (this=0x8097288) at test1.cc:14
> #12 0x0804d1c2 in Dlg::OnClicked (this=0xbfffcd04) at test1.cc:34
> #13 0x0804cfd4 in sigc::adaptor_functor<sigc::bound_mem_functor0<void,
> Dlg> >::operator() (this=0xbfffcd04) at mem_fun.h:1781
> #14 0x0804cf9a in
> sigc::internal::slot_call0<sigc::bound_mem_functor0<void, Dlg>,
> void>::call_it (rep=0x80a6980) at slot.h:103
> #15 0x4065a44d in Glib::SignalProxyNormal::slot0_void_callback ()
> from /usr/lib/libglibmm-2.4.so.1
> ...
>
> o Explanation of the backtrace
>
> Essentially, we are inside the invokation of the sigc::mem_fun(this,
> &Dlg::OnClicked) slot (frame 14) when we are deleting the Dlg instance
> (frame 11). Destroying the Dlg instance destroys the button, but the
> destruction of the sigc::mem_fun(this, &Dlg::OnClicked) slot is delayed
> because we are in the middle of invoking it. Once the Dlg destructor has
> finished, the sigc::trackable destructor is called (frame 10) because
> Dlg inherits from Gtk::Window, which inherits from trackable. Because
> the trackable is going away, it notifies all interested parties (frame
> 8). One such party happens to be the sigc::mem_fun(this,
> &Dlg::OnClicked) slot itself (frame 7), and in response to that
> notification, the slot is telling all the trackables it is bound to that
> it doesn't want to be notified by them anymore (frame 2). One such
> trackable is the Dlg instance itself. But the first time the address of
> the trackable is dereferenced (frame 0), the binary gets a SEGV because
> it is dereferencing an invalid pointer in file trackable.cc:
>
> internal::trackable_callback_list* trackable::callback_list() const
> {
> if (!callback_list_) <--- *** SEGV occurs here ***---
> callback_list_ = new internal::trackable_callback_list;
>
> return callback_list_;
> }
>
> o Possible explanation for the SEGV
>
> It seems that the address of the trackable is coming from this snippet
> in visit_each.h:
>
> template <class T_type> struct with_type<true,T_type>
> { static void execute_(const T_type& _A_type, const T_self& _A_action)
> { _A_action.action_(&_A_type); } <--- Here
> };
>
> At that very moment, the type of '_A_type' is 'Dlg' as shown in frame 2,
> and libsigc++ is trying to obtain a sigc::trackable pointer from it
> by using the '&' operator. Apparently, because the 'Dlg' facet of the
> object is already gone (we are in frames < 11), this confuses g++ big
> time and the '&' operator returns an invalid value. Note that Dlg
> inherits _virtually_ from Foo. It might be the cause of g++'s confusion.
>
> Conclusion
> ----------
> We don't know if there is a bug in the g++ optimizer, or if what
> libsigc++ is doing is unspecified by C++ standards.
This probably belongs in bugzilla, where it can be explored more. You should give full details about your platform there.
Sorry for not being more knowledgeable.
--
Murray Cumming
murrayc murrayc com
www.murrayc.com
www.openismus.com
#include <gtkmm.h>
class Bar
{
public:
virtual ~Bar()
{
}
};
class Dlg
: public Bar,
public Gtk::Window
{
public:
Dlg()
{
Gtk::Button *button = new Gtk::Button("Discard");
button->show();
add(*Gtk::manage(button));
button->signal_clicked().connect(sigc::mem_fun(this, &Dlg::OnClicked));
}
private:
void OnClicked()
{
delete this;
}
};
int main(int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
Dlg *toplevel = new Dlg();
toplevel->show();
kit.run();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]