Crashing after emplace_back

Hello people, I have a problem with this app... it keeps crashing after (I'm guessing) emplace_back on the container.

Here is a link: http://cpp.sh/7v2o

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
 

// Example program
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <bitset>
#include <queue>

template<typename C, typename... Args>
std::unique_ptr<C> make_unique(Args&&... args)
{
    return std::unique_ptr<C>(new C(std::forward<Args>(args)...));
}

class Container;
class Object;

struct Command
{
    Command() {}

    std::function<void(Object&, const float&)> action;
    int types;

};//Command
class Object
{
    public:
    Object(Container& container) : mContainer(container){}

    void onCommand(const Command& c, const float& dt)
    {
        c.action(*this,dt);
    }

    Container& mContainer;

};
class Container
{
    public:
    std::vector< std::unique_ptr<Object> > objects;
};
class CommandQueue
{
public:
    void        push(const Command& command)
    {
    m_Queue.push(command);
    }

    Command     front()
    {
    return m_Queue.front();
    }
    Command     pop()
    {
    Command command = m_Queue.empty() ? Command() : front();
    m_Queue.pop();
    return command;
    }

    std::queue<Command>   m_Queue;

};//CommandQueue
Container myContainer;
CommandQueue mQ;


int main()
{
    int input;
    myContainer.objects.emplace_back( make_unique<Object>(myContainer) );
    while(myContainer.objects.size() < 10)
    {
    std::cin >> input;
    
    if( input == 1 ) // I'm using a library to handle input obviously so it looks like this INPUT::KEYBOARD::X pretend this only gets called when the X key is hit
    {
        Command Attack;

         Attack.types = 1;
         Attack.action = []( Object& o, float )
         {
             std::cout<<  myContainer.objects.size() << "\n";
             o.mContainer.objects.emplace_back( make_unique<Object>(o.mContainer) );
         };
         mQ.push(Attack);
    }
    
    while(!mQ.m_Queue.empty())
    {
        for( auto& a : myContainer.objects)
        {
            a->onCommand(mQ.front(),1);
        }
       mQ.pop();
    }
    }
    
    return 0;
}


If you run it and input 1 about 3 times the program crashes... and I don't understand why... some light please?

http://s10.postimg.org/9d9zhv24n/Untitled.png
Last edited on
It's crashing because you are trying to use a vector of unique_ptr. Don't do that.

(I could be wrong about the actual cause of the crash that you are experiencing -- this is just a 'quick glance' diagnosis -- kind of like, while you're here at the hospital, let me take that knife out of you.)
I believe you are right, but I just changed the lambda from this:
1
2
3
4
5
Attack.action = []( Object& o, float )
{
  std::cout<<  myContainer.objects.size() << "\n";
  o.mContainer.objects.emplace_back( make_unique<Object>(o.mContainer) );
};


to this:

1
2
3
4
5
Attack.action = []( Object&, float )
{
  std::cout<<  myContainer.objects.size() << "\n";
  myContainer.objects.emplace_back(make_unique<Object>(myContainer));
};


the second version works fine because I am handling the global versions of the variables, is it the lifetime of the Object inside the lambda that is causing this?
Last edited on
You are adding things to a vector in a loop which uses an iterator to the same vector. Doing so can invalidate existing iterators if a reallocation is called for, so don't do this unless you can be sure a reallocation will not be called for.

It doesn't have anything to do with type of elements contained in your vector, and it doesn't matter what alias you're using to add to name the container.
Last edited on
So, if I just use the normal loop to iterate it should be fine? right?

that was my first thought but I tried to duplicate it by using a loop like this:

1
2
3
4
for(std::size_t i = 0; i < 40; ++i)
{
myVector.emplace_back(arg);
}



You are completely right cire, modifying a vector while iterating was stupid... I only got my self to blame, thank you.

If you use
1
2
3
4
5
auto size = myVector.objects.size();
for( std::size_t i = 0; i < size; ++i)
{
myVector.emplace_back(arg);
}

it works just fine, still I would steer away from this practice...
Last edited on
Topic archived. No new replies allowed.