Note: This is a beta release of Red Hat Bugzilla 5.0. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Also email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback here.
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
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:


Attachments (Terms of Use)
test.cpp (deleted)
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.