Description of problem: The attached the testcase, test.cpp, generates seg fault at run time How reproducible: It works fine with Sun CC and IBM xlC. However, I tried with gcc323, gcc4.1.x and gcc44, they all failed. Actual results: $ g++44 -m64 test.cpp $ ./a.out in my_object ctor in my_module ctor, setting up ptr in my_object ctor in my_module ctor, setting up ptr in wire_if ctor in my_object ctor in wire_slave_base ctor in wire_test_target ctor in top dtor in wire_test_target dtor in wire_slave_base dtor in my_object dtor before DCASTing to my_module* Segmentation fault Expected results: > ./a.out.sun in my_object ctor in my_module ctor, setting up ptr in my_object ctor in my_module ctor, setting up ptr in wire_if ctor in my_object ctor in wire_slave_base ctor in wire_test_target ctor in top dtor in wire_test_target dtor in wire_slave_base dtor in my_object dtor before DCASTing to my_module* after DCASTing to my_module* in wire_if dtor in my_module dtor in my_object dtor before DCASTing to my_module* after DCASTing to my_module* in my_module dtor in my_object dtor before DCASTing to my_module* after DCASTing to my_module* Additional info: The same results on all g++ version I have tested. And failed for both -m32 and -m64. This looks very similar to a previous Cadence issue: https://enterprise.redhat.com/issue-tracker/?module=issues&action=view&tid=314103 however, this test program fails using the patch from that issue. I have also reproduced the issue on Fedora 11. I have not tried the latest upstream gcc. If the reproducer is a well formed C++ program then this looks to be a problem in the dyanmic cast runtime code.
Created attachment 414670 [details] test.cpp
As quoted in issue 314103: 12.7/6: "Dynamic_casts (5.2.7) can be used during construction or destruction (12.6.2). When a dynamic_cast is used in a constructor (including from the mem-initializer or brace-or-equal-initializer for a non-static data member) or in a destructor, or used in a function called (directly or indirectly) from a constructor or destructor, if the operand of the dynamic_cast refers to the object under construction or destruction, this object is considered to be a most derived object that has the type of the constructor or destructor’s class. If the operand of the dynamic_cast refers to the object under construction or destruction and the static type of the operand is not a pointer to or object of the constructor or destructor’s own class or one of its bases, the dynamic_cast results in undefined behavior." Here "my_module_ptr" refers to the my_module base of wire_test_target, and we're destroying the my_object member of the wire_slave_base base of wire_test_target. In this example wire_if is the primary base class of both wire_test_target and wire_slave_base (see -fdump-class-hierarchy for the details), so once we start destroying wire_slave_base the wire_test_target virtual table pointer now points to a construction vtable for wire_if in wire_slave_base which doesn't know anything about my_module. But the vtable pointers for my_module and my_object still think they're part of a wire_test_target, so dynamic_cast converts to wire_test_target and then tries to find the offset to the my_module base. But that offset doesn't exist in the wire_if vtable, so we crash. I believe this is undefined under the rules above: the pointer refers to the wire_test_target object which is under destruction, but is not a pointer to wire_slave_base or one of its bases.
But as before, I'm not sure if "the object under destruction" is supposed to mean the complete wire_test_target object or just the my_object subobject.
Actually, the example in 12.7 paragraph 6 is very similar to this testcase, and I think makes it clear that this testcase has undefined behavior. I will still investigate further to see if it's possible to do what you want without breaking the ABI.
I don't think it's possible. The different from issue 314103 is that in that case the desired my_module was a non-virtual base of C the most derived class, so we didn't need to look in the vtable for the most derived class to find it. In this case there is a my_module that is a non-virtual base of top, but the my_module that my_module_ptr points to at the time of the dynamic_cast is a virtual base of a wire_test_target object.