Aug 18, 2015 at 11:05pm UTC
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 Aug 18, 2015 at 11:55pm UTC
Aug 19, 2015 at 12:17am UTC
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.)
Aug 19, 2015 at 12:30am UTC
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 Aug 19, 2015 at 12:57am UTC
Aug 19, 2015 at 1:18am UTC
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 Aug 19, 2015 at 1:18am UTC
Aug 19, 2015 at 1:32am UTC
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 Aug 19, 2015 at 2:50am UTC