Folks,

We are 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.

Command line
------------
g++ -v -save-temps -O -g `pkg-config --cflags --libs gtkmm-2.4` test1.cc -o 
test1

Where `pkg-config --cflags --libs gtkmm-2.4` expands to:
-DXTHREADS -D_REENTRANT -DXUSE_MTSAFE_API -I/usr/include/gtkmm-2.4
-I/usr/lib/gtkmm-2.4/include -I/usr/include/glibmm-2.4
-I/usr/lib/glibmm-2.4/include -I/usr/include/gdkmm-2.4
-I/usr/lib/gdkmm-2.4/include -I/usr/include/pangomm-1.4 -I/usr/include/atkmm-1.6
-I/usr/include/gtk-2.0 -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include
-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/gtk-2.0/include
-I/usr/X11R6/include -I/usr/include/pango-1.0 -I/usr/include/freetype2
-I/usr/include/freetype2/config -I/usr/include/atk-1.0  -Wl,--export-dynamic
-lgtkmm-2.4 -lgdkmm-2.4 -latkmm-1.6 -lgtk-x11-2.0 -lpangomm-1.4 -lglibmm-2.4
-lsigc-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangoxft-1.0
-lpangox-1.0 -lpango-1.0 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0

Command line output
-------------------
o TTY output:
Reading specs from /usr/lib/gcc-lib/i486-slackware-linux/3.3.4/specs
Configured with: ../gcc-3.3.4/configure --prefix=/usr --enable-shared
--enable-threads=posix --enable-__cxa_atexit --disable-checking --with-gnu-ld
--verbose --target=i486-slackware-linux --host=i486-slackware-linux
Thread model: posix
gcc version 3.3.4
 /usr/lib/gcc-lib/i486-slackware-linux/3.3.4/cc1plus -E -D__GNUG__=3 -quiet -v
-I/usr/include/gtkmm-2.4 -I/usr/lib/gtkmm-2.4/include -I/usr/include/glibmm-2.4
-I/usr/lib/glibmm-2.4/include -I/usr/include/gdkmm-2.4
-I/usr/lib/gdkmm-2.4/include -I/usr/include/pangomm-1.4 -I/usr/include/atkmm-1.6
-I/usr/include/gtk-2.0 -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include
-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/gtk-2.0/include
-I/usr/X11R6/include -I/usr/include/pango-1.0 -I/usr/include/freetype2
-I/usr/include/freetype2/config -I/usr/include/atk-1.0 -D__GNUC__=3
-D__GNUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=4 -D_GNU_SOURCE -DXTHREADS -D_REENTRANT
-DXUSE_MTSAFE_API test1.cc -O test1.ii
ignoring nonexistent directory "/usr/include/freetype2/config"
ignoring nonexistent directory "/usr/i486-slackware-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/gtkmm-2.4
 /usr/lib/gtkmm-2.4/include
 /usr/include/glibmm-2.4
 /usr/lib/glibmm-2.4/include
 /usr/include/gdkmm-2.4
 /usr/lib/gdkmm-2.4/include
 /usr/include/pangomm-1.4
 /usr/include/atkmm-1.6
 /usr/include/gtk-2.0
 /usr/include/sigc++-2.0
 /usr/lib/sigc++-2.0/include
 /usr/include/glib-2.0
 /usr/lib/glib-2.0/include
 /usr/lib/gtk-2.0/include
 /usr/X11R6/include
 /usr/include/pango-1.0
 /usr/include/freetype2
 /usr/include/atk-1.0
 /usr/lib/qt/include
 /usr/include/c++/3.3.4
 /usr/include/c++/3.3.4/i486-slackware-linux
 /usr/include/c++/3.3.4/backward
 /usr/local/include
 /usr/lib/gcc-lib/i486-slackware-linux/3.3.4/include
 /usr/include
End of search list.
 /usr/lib/gcc-lib/i486-slackware-linux/3.3.4/cc1plus -fpreprocessed test1.ii
-quiet -dumpbase test1.cc -auxbase test1 -g -O -version -o test1.s
GNU C++ version 3.3.4 (i486-slackware-linux)
        compiled by GNU C version 3.3.4.
GGC heuristics: --param ggc-min-expand=90 --param ggc-min-heapsize=113063
usr/lib/gcc-lib/i486-slackware-linux/3.3.4/../../../../i486-slackware-linux/bin/as
-V -Qy -o test1.o test1.s
GNU assembler version 2.15.92.0.2 (i486-slackware-linux) using BFD version
2.15.92.0.2 20040927
 /usr/lib/gcc-lib/i486-slackware-linux/3.3.4/collect2 --eh-frame-hdr -m elf_i386
-dynamic-linker /lib/ld-linux.so.2 -o test1
/usr/lib/gcc-lib/i486-slackware-linux/3.3.4/../../../crt1.o
/usr/lib/gcc-lib/i486-slackware-linux/3.3.4/../../../crti.o
/usr/lib/gcc-lib/i486-slackware-linux/3.3.4/crtbegin.o
-L/usr/lib/gcc-lib/i486-slackware-linux/3.3.4
-L/usr/lib/gcc-lib/i486-slackware-linux/3.3.4/../../../../i486-slackware-linux/lib
-L/usr/lib/gcc-lib/i486-slackware-linux/3.3.4/../../.. --export-dynamic
-lgtkmm-2.4 -lgdkmm-2.4 -latkmm-1.6 -lgtk-x11-2.0 -lpangomm-1.4 -lglibmm-2.4
-lsigc-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lpangoxft-1.0 -lpangox-1.0
-lpango-1.0 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 test1.o -lstdc++ -lm
-lgcc_s -lgcc -lc -lgcc_s -lgcc
/usr/lib/gcc-lib/i486-slackware-linux/3.3.4/crtend.o
/usr/lib/gcc-lib/i486-slackware-linux/3.3.4/../../../crtn.o

o Pre-processed file output
A compressed (bzip2 -9) version of file test1.ii is attached.

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.

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> ([EMAIL PROTECTED],
    [EMAIL PROTECTED]) 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> ([EMAIL PROTECTED],
    [EMAIL PROTECTED]) 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> >
([EMAIL PROTECTED], [EMAIL PROTECTED]) 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> > > (
    [EMAIL PROTECTED], [EMAIL PROTECTED]) 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.

-- 
           Summary: Invalid value returned by operator '&' when -O is used
           Product: gcc
           Version: 3.3.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: hpreg at vmware dot com
                CC: gcc-bugs at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20304

Reply via email to