Bug 965339 - set::erase(position) is ABI-incompatible between C++98 and C++11
Summary: set::erase(position) is ABI-incompatible between C++98 and C++11
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc
Version: 18
Hardware: i686
OS: Linux
unspecified
unspecified
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2013-05-21 00:46 UTC by Josh Stone
Modified: 2014-02-05 23:47 UTC (History)
5 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2014-02-05 23:25:49 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Josh Stone 2013-05-21 00:46:33 UTC
Description of problem:
There are two similar forms of set::erase(position):
(C++98) void erase (iterator position);
(C++11) iterator erase (const_iterator position);

Because of that return value, these have different calling ABI - at least on i686 you get an extra hidden parameter for the iterator return.  However, both of these functions mangle to the same thing:

_ZNSt3setIiSt4lessIiESaIiEE5eraseESt23_Rb_tree_const_iteratorIiE

demangled:
std::set<int, std::less<int>, std::allocator<int> > ::erase(std::_Rb_tree_const_iterator<int>)

That's despite the different "position" parameter types, because std::set actually defines them as:

typedef typename _Rep_type::const_iterator            iterator;
typedef typename _Rep_type::const_iterator            const_iterator;

Thus, if a program has executable/libraries with a mix of C++98 and C++11, and they're not optimized (so set::erase is not inlined), then at runtime some of the plt calls will get resolved to the ABI-incompatible version from the others, and mayhem ensues.


Version-Release number of selected component (if applicable):
libstdc++-4.7.2-8.fc18.i686

How reproducible:
100%

Steps to Reproduce:

1. Save as libsetabi.cc:
#include <set>
void erase_first(std::set<int>& s)
{
    s.erase(s.begin());
}

2. Save as setabi.cc:
#include <set>
void erase_first(std::set<int>& s);
int main()
{
    std::set<int> s{0,1};
    erase_first(s);
    s.erase(s.begin());
    return s.size();
}

3. Run:
$ g++ -m32 -std=c++98 -shared -fPIC libsetabi.cc -o libsetabi.so
$ g++ -m32 -std=c++11 setabi.cc -o setabi -L. -lsetabi -Wl,-rpath=.
$ ./setabi

Actual results:
Segmentation fault
($? == 139)

Expected results:
($? == 0)

Additional info:
This was reported to me as a problem found in Dyninst by Bill Williams.

And I fully expect this is an upstream problem, but I'm only set up to test directly on Fedora, so I thought it best to file here first.

Comment 1 Josh Stone 2013-05-21 01:01:42 UTC
The result is the same on rawhide, libstdc++-4.8.0-6.fc20.i686.

Also, the GCC wiki does mention the change in set::erase, but supposes it's ok because of the const_iterator difference.  I expect that was the intention of the standards committee when making this change, but as I noted above, the set::iterator typedef breaks this distinction.
http://gcc.gnu.org/wiki/Cxx11AbiCompatibility

Comment 2 Benjamin Kosnik 2013-05-21 01:28:19 UTC
Confirmed as upstream issue on i686. On x86_64 getting lucky with layout sidesteps the issue.

This is from the DR 130 resolution. Return types are not mangled, but changed between the two dialects, thus this issue.

Bummer.

Comment 3 Josh Stone 2013-05-21 02:27:54 UTC
For anyone like me who is unfamiliar, this is DR 130:
http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#130

DR 103 is also relevant for the immutable set::iterator type:
http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#103

That added for containers like set, "It is unspecified whether or not iterator and const_iterator are the same type."  It seems this bug demonstrates why they ought to be made distinct, but I guess that would change ABI across the board.

Comment 4 Benjamin Kosnik 2013-05-21 17:13:06 UTC
Nice job reporting this Josh, and thanks for the clear example.

Comment 5 Jason Merrill 2013-05-28 00:51:11 UTC
In 4.8.x we can use an abi_tag to change the mangled name of the C++11 version...

Comment 6 Josh Stone 2013-05-28 17:39:38 UTC
Nice, abi_tag sounds perfectly appropriate to me.

And just for completeness, I tested and confirmed that a multiset version of the given example exhibits the same issue.

Comment 7 Benjamin Kosnik 2013-06-11 01:45:06 UTC
Here is the patch for trunk:
http://gcc.gnu.org/ml/gcc-patches/2013-06/msg00548.html

Soon to be on 4.8 branch.

Comment 8 Fedora End Of Life 2013-12-21 15:53:07 UTC
This message is a reminder that Fedora 18 is nearing its end of life.
Approximately 4 (four) weeks from now Fedora will stop maintaining
and issuing updates for Fedora 18. It is Fedora's policy to close all
bug reports from releases that are no longer maintained. At that time
this bug will be closed as WONTFIX if it remains open with a Fedora 
'version' of '18'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version prior to Fedora 18's end of life.

Thank you for reporting this issue and we are sorry that we may not be 
able to fix it before Fedora 18 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora, you are encouraged  change the 'version' to a later Fedora 
version prior to Fedora 18's end of life.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

Comment 9 Fedora End Of Life 2014-02-05 23:25:49 UTC
Fedora 18 changed to end-of-life (EOL) status on 2014-01-14. Fedora 18 is
no longer maintained, which means that it will not receive any further
security or bug fix updates. As a result we are closing this bug.

If you can reproduce this bug against a currently maintained version of
Fedora please feel free to reopen this bug against that version. If you
are unable to reopen this bug, please file a new report against the
current release. If you experience problems, please add a comment to this
bug.

Thank you for reporting this bug and we are sorry it could not be fixed.

Comment 10 Josh Stone 2014-02-05 23:47:16 UTC
I guess Ben just forgot to update this, but FWIW this is fine on F20 libstdc++-4.8.2-7.fc20.i686, and probably also F19 as it has the same version.


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