http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48038
Summary: stable_sort problem with C++0x and comparator by value
Product: gcc
Version: 4.6.0
Status: UNCONFIRMED
Severity: critical
Priority: P3
Component: libstdc++
AssignedTo: [email protected]
ReportedBy: [email protected]
if one uses a comparator where arguments are passed by value such as
inline bool operator<(V rh, V lh) {
something goes wrong with "move" and default constructed objects are passed in
the comparator
It happens in stable_sort for sure
I'm using a recent version of 4.6
g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/4.6.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ./configure --enable-gold=yes --enable-lto --with-fpmath=avx
Thread model: posix
gcc version 4.6.0 20110205 (experimental) (GCC)
this is an example I use that produces a seg-fault (easy to detect)
g++ -O2 -std=gnu++0x -g rvalue.cpp -DBYVALUE
will seg-fault
g++ -O2 -std=gnu++0x -g rvalue.cpp
is ok
the seg-fault is in
Program received signal SIGSEGV, Segmentation fault.
std::merge<std::move_iterator<V*>,
std::move_iterator<__gnu_cxx::__normal_iterator<V*, std::vector<V,
std::allocator<V> > > >, __gnu_cxx::__normal_iterator<V*, std::vector<V,
std::allocator<V> > > > (__first1=..., __last1=..., __first2=<value optimized
out>, __last2=...,
__result=<value optimized out>) at
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/bits/stl_algo.h:5390
5390 if (*__first2 < *__first1)
Missing separate debuginfos, use: debuginfo-install
glibc-2.12-1.7.el6_0.3.x86_64
(gdb) where
#0 std::merge<std::move_iterator<V*>,
std::move_iterator<__gnu_cxx::__normal_iterator<V*, std::vector<V,
std::allocator<V> > > >, __gnu_cxx::__normal_iterator<V*, std::vector<V,
std::allocator<V> > > > (__first1=..., __last1=..., __first2=<value optimized
out>, __last2=...,
__result=<value optimized out>) at
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/bits/stl_algo.h:5390
#1 0x0000000000406f86 in
std::__merge_adaptive<__gnu_cxx::__normal_iterator<V*, std::vector<V,
std::allocator<V> > >, long, V*> (__first=...,
__middle=..., __last=..., __len1=<value optimized out>, __len2=<value
optimized out>, __buffer=0x615cc0, __buffer_size=6)
at
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/bits/stl_algo.h:2835
#2 0x0000000000408195 in
std::__stable_sort_adaptive<__gnu_cxx::__normal_iterator<V*, std::vector<V,
std::allocator<V> > >, V*, long> (
__first=..., __last=..., __buffer=0x615cc0, __buffer_size=6)
at
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/bits/stl_algo.h:3312
#3 0x000000000040d0e0 in stable_sort<__gnu_cxx::__normal_iterator<V*,
std::vector<V, std::allocator<V> > > > ()
at
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/bits/stl_algo.h:5508
#4 go<V> () at rvalue.cpp:114
#5 0x000000000040f6f9 in main () at rvalue.cpp:135
the test program
cat rvalue.cpp
#include <vector>
#include <iostream>
#include<functional>
#include<algorithm>
typedef std::vector<double> VI;
struct V {
VI v;
V(){std::cout <<"dc" << std::endl;}
virtual ~V(){std::cout <<"dd " << v.size()<< std::endl;}
V(V const & rh) : v(rh.v) {
std::cout <<"cc" << std::endl;
}
V(size_t n, double d) : v(n,d){}
V & operator=(V const &rh) {
std::cout <<"ac" << std::endl;
V tmp(rh);
v.swap(tmp.v);
return *this;
}
#if defined( __GXX_EXPERIMENTAL_CXX0X__)
V(V && rh) : v(std::move(rh.v)) {
std::cout <<"rc" << std::endl;
}
V & operator=(V && rh) {
std::cout <<"ar" << std::endl;
std::swap(rh.v,v);
return *this;
}
#else
void swap(V & rh) {
std::cout <<"V::swap" << std::endl;
std::swap(rh.v,v);
}
#endif
};
struct A : public V {
A(size_t n, double d) : V(n,d){}
};
/*
inline
void swap(V & lh, V & rh) {
std::cout <<"::swap" << std::endl;
std::swap(lh.v,rh.v);
}
*/
#ifdef BYVALUE
inline bool operator<(V rh, V lh) {
#else
inline bool operator<(V const& rh, V const& lh) {
#endif
return rh.v[0]<lh.v[0];
}
template<typename T>
void go() {
std::vector<T> vvs;
std::cout << "push_back " << std::endl;
vvs.push_back(T(50,0.));
for (int i=1;i<5; ++i)
vvs.push_back(T(100*i,i));
std::cout << "push_front " << std::endl;
vvs.insert(vvs.begin(),T(300,1.));
#if defined( __GXX_EXPERIMENTAL_CXX0X__)
auto vov = std::bind(&T::v,std::placeholders::_1);
vov(vvs[0]).size();
auto myless = std::bind<bool>(std::less<VI>(),
std::bind<VI const&>(&V::v,std::placeholders::_1),
std::bind<VI const&>(&V::v,std::placeholders::_2)
);
std::cout << ( myless(vvs[0],vvs[2]) ? "less" : "greater" ) << std::endl;
#endif
std::cout << "shuffle " << std::endl;
std::random_shuffle(vvs.begin(),vvs.end());
std::cout << "sort " << std::endl;
std::sort(vvs.begin(),vvs.end());
#if defined( __GXX_EXPERIMENTAL_CXX0X__)
std::cout << "sort myless" << std::endl;
std::sort(vvs.begin(),vvs.end(), myless);
#endif
std::cout << "stable sort " << std::endl;
std::stable_sort(vvs.begin(),vvs.end());
#if defined( __GXX_EXPERIMENTAL_CXX0X__)
std::cout << "stable sort myless" << std::endl;
std::stable_sort(vvs.begin(),vvs.end(), myless);
#endif
{
std::cout << "swap " << std::endl;
T v(5,3.);
std::swap(v,vvs[3]);
std::cout << "swap done" << std::endl;
}
for (int i=1;i<vvs.size(); ++i)
std::cout << vvs[i].v.size() << ", ";
std::cout << "\nthe end\n" << std::endl;
}
int main() {
go<V>();
go<A>();
return 0;
}