12

I encountered a strange segfault in a big project; finally I managed to locate the code and dump the data. Here is a simplified program:

#include <cstdlib>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

const float DATA[] = {
    0.179697, -0.413853, -0.079650, 0.167255, -1.263407, 1.707440, -0.162176,
    -0.176349, -0.826179, -0.097582, -0.265471, 0.070675, 0.077035, -0.218272,
    -0.509723, -0.244462, 0.000000, -0.069970, -0.169399, 0.236123, -1.063037,
    0.048428, 0.080877, -0.099672, -0.580204, -0.174694, -0.082321, -0.313485,
    1.828802, -0.110842, -0.367741, 0.026412, 0.116269, -0.164420, -0.726286,
    -0.335257, 0.456737, -0.465721, -0.242003, -0.755520, -1.155553, 0.013372,
    -0.033874, -0.105618, 0.000000, -0.578532, -0.057074, 0.026309, -0.978317,
    -0.253747
};

int main() {
    std::vector<float> arr(DATA, DATA + sizeof(DATA) / sizeof(DATA[0]));

    /*
    for (std::vector<float>::iterator i = arr.begin();
            i != arr.end(); i ++)
        *i = rand() / (RAND_MAX + 1.0);
        */

    // std::sort(arr.begin(), arr.end());
    std::nth_element(arr.begin(), arr.begin() + 1, arr.end());
    std::nth_element(arr.begin(), arr.end() - 1, arr.end());
    cout << arr.back() << endl;
}

Thanks for reading up here! The problem is that this program, if supplied with this data, would segfault on my machine (if it works on your machine, you can try running it with valgrind) ; However, if I uncomment any of those commented two blocks (i.e. use random data, or first sort the array), the program would run as expected.

I have tried with clang 3.3 and gcc 4.8.2, compiling with/without -O2, under c++03/c++11; it's always the same. I use archlinux, x64, libstdc++5 3.3.6.

Thanks very much for your kind help :)

segfault backtrace:

#0  0x0000000000401a9f in std::__unguarded_partition<__gnu_cxx::__normal_iterator<float*, std::vector<float, std::allocator<float> > >, float> (
    __first=<error reading variable: Cannot access memory at address 0x625000>, __last=1.89120642e-40, __pivot=@0x6040c8: 1.82880199)
    at /usr/include/c++/4.8.2/bits/stl_algo.h:2242
#1  0x0000000000401497 in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<float*, std::vector<float, std::allocator<float> > > > (__first=1.82880199, 
    __last=1.89120642e-40) at /usr/include/c++/4.8.2/bits/stl_algo.h:2283
#2  0x0000000000401134 in std::__introselect<__gnu_cxx::__normal_iterator<float*, std::vector<float, std::allocator<float> > >, long> (__first=1.82880199, 
    __nth=0.236122996, __last=1.89120642e-40, __depth_limit=7) at /usr/include/c++/4.8.2/bits/stl_algo.h:2365
#3  0x0000000000400e48 in std::nth_element<__gnu_cxx::__normal_iterator<float*, std::vector<float, std::allocator<float> > > > (__first=-0.174694002, __nth=0.236122996, 
    __last=1.89120642e-40) at /usr/include/c++/4.8.2/bits/stl_algo.h:5377
#4  0x0000000000400b2c in main () at tnew.cc:29

edit: for archlinux, downgrading to gcc 4.8.1-3 solves the problem (sudo pacman -Ud /var/cache/pacman/pkg/gcc-multilib-4.8.1-3-x86_64.pkg.tar.xz)

jiakai
  • 501
  • 2
  • 14
  • 1
    You do know that `arr.begin() + SIZE - 1` would be the same as `arr.end() - 1`? (If you read `SIZE` values, that is.) – Some programmer dude Oct 22 '13 at 16:28
  • Are you sure you actually *read* `SIZE` elements from the file? There's no error checking. – Some programmer dude Oct 22 '13 at 16:28
  • Where exactly your program crash and what stack trace shows? – Slava Oct 22 '13 at 16:29
  • @Slava Please see the new edit :) – jiakai Oct 22 '13 at 16:38
  • @JoachimPileborg Thanks for your advice, I have changed the code:) Still segfault ... – jiakai Oct 22 '13 at 16:42
  • To isolate problems like this, remove the file input and stuff hard-coded values into the vector. That will help you figure out whether the problem is in the data or in the code that manipulates it. And it will make it much easier for folks online to reproduce your problem. – Pete Becker Oct 22 '13 at 16:43
  • @PeteBecker At first I fear that embedding floating point literally would change their values; now I've updated the code, which is much more clear. Thanks for your advice :) – jiakai Oct 22 '13 at 16:56
  • Your newest code works fine over on ideone: http://ideone.com/nysRUp – JaredC Oct 22 '13 at 16:58
  • Works for me, gcc 4.2.1, gcc 4.7.0, gcc 4.8.1, clang 4.2. – Pete Becker Oct 22 '13 at 16:59
  • 2
    SEGFAULT on g++4.8.1 and clang++3.4, libstdc++4.8.1 – dyp Oct 22 '13 at 17:00
  • So this seems to be a bug introduced since some version of g++? But I really need c++11 Any solutions? Maybe it's better to implement my own nth_element. – jiakai Oct 22 '13 at 17:03
  • Works for me, g++ 4.7.2, linux 64 bit, clang 3.4 trunk. – Ali Oct 22 '13 at 17:03
  • Works for me on GCC 4.7.3 and clang 3.4 (Ubuntu 13.04 x64). – detunized Oct 22 '13 at 17:06
  • @jiakai Not sure why it fails with g++ 4.8.1 (as reported by you and other members). However, instead of std::nth_element, you can try 'boost::nth_element' before implementing your own algorithm. – user2784234 Oct 22 '13 at 17:07

1 Answers1

12

You seem to hit this bug so you should update libstdc++ at least to 4.8.3

Slava
  • 43,454
  • 1
  • 47
  • 90
  • segfault still in g++4.9 2013-10-15; I'm updating it now to see if it has been resolved for this case. – dyp Oct 22 '13 at 17:39
  • libstdc++ is included in the svn repo of gcc. I should have said that I'm compiling both from trunk. – dyp Oct 22 '13 at 17:43
  • @DyP last comment there about fix published 2013-10-20 – Slava Oct 22 '13 at 17:47
  • Yes, that's why I'm compiling it right now to see if it has been fixed ;) – dyp Oct 22 '13 at 17:47
  • No segfault in gcc/g++4.9 2013-10-22 (including updated libstdc++); problem has indeed been fixed. – dyp Oct 23 '13 at 19:51