Bug 593124 - g++44 problem - crashes in dynamic cast runtime code
Summary: g++44 problem - crashes in dynamic cast runtime code
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Red Hat Enterprise Linux 5
Classification: Red Hat
Component: gcc44
Version: 5.5
Hardware: All
OS: Linux
high
high
Target Milestone: rc
: ---
Assignee: Jakub Jelinek
QA Contact: qe-baseos-tools-bugs
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2010-05-17 21:21 UTC by Alan Matsuoka
Modified: 2018-10-27 12:15 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2010-05-31 13:39:35 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
test.cpp (1.69 KB, text/x-c++src)
2010-05-17 21:22 UTC, Alan Matsuoka
no flags Details

Description Alan Matsuoka 2010-05-17 21:21:41 UTC
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.

Comment 1 Alan Matsuoka 2010-05-17 21:22:40 UTC
Created attachment 414670 [details]
test.cpp

Comment 2 Jason Merrill 2010-05-18 22:04:46 UTC
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.

Comment 3 Jason Merrill 2010-05-19 00:34:54 UTC
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.

Comment 4 Jason Merrill 2010-05-19 00:41:41 UTC
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.

Comment 5 Jason Merrill 2010-05-19 15:31:33 UTC
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.


Note You need to log in before you can comment on or make changes to this bug.