-2

I was trying to understand functors. I have the below program which I borrowed and modified from functors and their uses.

#include <iostream>                                                                                                                                                                                                                          
#include <vector>
#include <assert.h>
#include <algorithm>

/*
 * A functor is pretty much just a class which defines the operator(). 
 * That lets you create objects which "look like" a function
 **/
struct add_x
{
    add_x(int y) : x(y) 
    {   

    }   
    int operator()(int y) const {
        return x + y;
    }   

private:
    int x;
};

int main()
{
    /* create an instance of the functor class*/
    add_x add42(42);
    /* and "call" it */
    int i = add42(8); 
    /*and it added 42 to its argument*/
    assert(i == 50); 

    /*assume this contains a bunch of values*/
    std::vector<int> in; 
    std::vector<int> out(in.size());
    /*  
     * Pass a functor to std::transform, which calls the functor on every element
     * in the input sequence, and stores the result to the output sequence
     */
    std::transform(in.begin(), in.end(), out.begin(), add_x(1));
    /*for all i*/
    assert(out[i] == (in[i] + 1)); 
    return 0;
}

I am getting a segmentation fault in the second assert statement in main(). (assert(out[i] == (in[i] + 1));)I can't seem to figure out why?

Community
  • 1
  • 1
liv2hak
  • 14,472
  • 53
  • 157
  • 270
  • 3
    `int i = add42(8);` and then you use `i` later to index into an empty `vector`. Bugs like these should be trivial to figure out if you run under a debugger. – Praetorian Feb 11 '16 at 02:25
  • Please provide [a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – James Adkison Feb 11 '16 at 02:26
  • 3
    `/*assume this contains a bunch of values*/` no, I will *not*. You need to provide actual code for us to figure out why it breaks. Clearly the above code breaks, it is accessing the 50th element of an empty array. Your code? Has some problem we cannot diagnose. Do not simply post all of your code, instead reproduce an actual example that remains simple yet you get your problem (say, actually populate the vectors? With fixed values?). Then test that your problem occurs in your simple case. – Yakk - Adam Nevraumont Feb 11 '16 at 02:28
  • 2
    Since you're using `assert`, you could have gone one step further and use `vector::at()` instead of `[ ]`. The runtime would have thrown a `std::out_of_range` exception with much more information instead of a segmentation fault. `assert(out.at(i) == (in.at(i) + 1));` I feel that newbies should always use `at()` first, and then when all of out-of-bounds access are resolved, then change to using `[ ]`. There are **lots** of questions concerning seg faults when using vector, and a great bulk of them have to do with `[ ]`. – PaulMcKenzie Feb 11 '16 at 02:28
  • 1
    @Praetorian The code comments (i.e., `/*assume this contains a bunch of values*/`) lead me to believe the full code wasn't provided (i.e., the "real" code actually has a non-empty `in` vector). – James Adkison Feb 11 '16 at 02:28
  • @JamesAdkison Yes, you're right. I missed that part until Yakk pointed it out. – Praetorian Feb 11 '16 at 02:29
  • 1
    Unrelated but you may also want to take a look at [`std::back_inserter`](http://en.cppreference.com/w/cpp/iterator/back_inserter), you could pair it with `std::vector::reserve` if there are a lot of elements. – James Adkison Feb 11 '16 at 02:38

1 Answers1

4

in.size() will return 0 because you haven't added anything to it yet. Which means out is being initialized as an empty vector.

out[i] will try to access the 51st element of the vector (as STL indexes are zero-based) which doesn't exist, hence the segfault.

The comment /*assume this contains a bunch of values*/ isn't helpful because your code doesn't show that in contains anything.

Use the vector(size_t n, const value_type& val) constructor overload to provide initial values for the vector to fix this bug:

using namespace std;

...

vector<int> in(51, 0); // initializes the vector with 51 values of zero
vector<int> out( in.size() ); // 51
...

assert( out[i] == int[i] + 1 );
Dai
  • 141,631
  • 28
  • 261
  • 374