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: unassig...@gcc.gnu.org ReportedBy: vincenzo.innoce...@cern.ch 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; }