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;
}

Reply via email to