Red Hat Bugzilla – Bug 965339
set::erase(position) is ABI-incompatible between C++98 and C++11
Last modified: 2014-02-05 18:47:16 EST
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:
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):
Steps to Reproduce:
1. Save as libsetabi.cc:
void erase_first(std::set<int>& s)
2. Save as setabi.cc:
void erase_first(std::set<int>& s);
$ 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=.
($? == 139)
($? == 0)
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.
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.
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.
For anyone like me who is unfamiliar, this is DR 130:
DR 103 is also relevant for the immutable set::iterator type:
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.
Nice job reporting this Josh, and thanks for the clear example.
In 4.8.x we can use an abi_tag to change the mangled name of the C++11 version...
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.
Here is the patch for trunk:
Soon to be on 4.8 branch.
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.
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
Thank you for reporting this bug and we are sorry it could not be fixed.
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.