Skip to main content
GameDev.net gamedev.net
🔒 Locked

std::vector help!

Started by acidic10 Oct 9, 2010 at 2:26 PM 11 replies 2.9k views
Original Post
acidic10
acidic10
I am trying to make a simple particle demo and I have two classes, "Particle" and "ParticleEmitter". The ParticleEmitter class has a pointer to a vector of pointers to "Particle" objects. For some reason I get Access Violation errors when trying to do anything with the vector, for example iterate through it. Can someone take a quick look and let me know where I'm going wrong?

ParticleEmitter.h
#ifndef __PARTICLE_EMITTER_H#define __PARTICLE_EMITTER_Hclass ParticleEmitter {    public:            ParticleEmitter();        ParticleEmitter(const Vector3f pPosition, const Vector3f pVelocity, int pNumParticles);        ~ParticleEmitter();                Vector3f getVelocity();        Vector3f getPosition();                void move();        void emit();        void draw();                private:        Vector3f m_Position;        Vector3f m_Velocity;        std::vector<Particle*> *m_Particles;};#endif


ParticleEmitter.cpp
ParticleEmitter::ParticleEmitter(const Vector3f pPosition, const Vector3f pVelocity, int pNumParticles) {    this->m_Position = pPosition;    this->m_Velocity = pVelocity;    this->m_Particles = new std::vector<Particle*>(pNumParticles);        for (int i=0; i<pNumParticles; i++) {        Particle *p = new Particle(100.0f, 100.0f, 100.0f), Vector3f(0.0f, 0.0f, 0.0f), 5, 20);        this->m_Particles->push_back(p);    }    }void ParticleEmitter::emit() {    std::vector<Particle*>::iterator particleIterator;    for (particleIterator = this->m_Particles.begin(); particleIterator != this->m_Particles.end(); ++particleIterator) {        (*particleIterator)->move();    }    }
emiel1
emiel1
You are creating a vector with pNumParticles with this line:
this->m_Particles = new std::vector<Particle*>(pNumParticles);
These are created as random pointers. Then you add pNumParticles to the vector, but at the back. The first pNumParticles pointers still point to random memory addresses.

You need to change the code to:

ParticleEmitter.h
#ifndef __PARTICLE_EMITTER_H#define __PARTICLE_EMITTER_Hclass ParticleEmitter{    public:        ParticleEmitter();        ParticleEmitter(const Vector3f pPosition, const Vector3f pVelocity, int pNumParticles);        ~ParticleEmitter();                Vector3f getVelocity();        Vector3f getPosition();                void move();        void emit();        void draw();                private:        Vector3f m_Position;        Vector3f m_Velocity;        std::vector<Particle*> m_Particles;};#endif


ParticleEmitter.cpp
ParticleEmitter::ParticleEmitter(const Vector3f pPosition, const Vector3f pVelocity, int pNumParticles) : m_Position(pPosition), m_Velocity(pVelocity){    for (int i=0; i<pNumParticles; i++) {        Particle *p = new Particle(Vector3f(100.0f, 100.0f, 100.0f), Vector3f(0.0f, 0.0f, 0.0f), 5, 20);        m_Particles.push_back(p);    }}void ParticleEmitter::emit(){    std::vector<Particle*>::iterator particleIterator;    for (particleIterator = m_Particles.begin(); particleIterator != m_Particles.end(); ++particleIterator) {        (*particleIterator)->emit();    }}


This includes various other changes:
- Removed "this->" before every member variable (not needed)
- Changed Particle::move() to Particle::emit() as the member function call in ParticleEmitter::emit() (probably what you meant)
- Changed the function call to the particle constructor to fit the definition of Particle (probably what you meant)
- Changed the ParticleEmitter constructor to use the member variable constructors (faster)

Emiel
acidic10
acidic10
Thanks for your response. I've made the changes you've listed but I'm still getting an access violation when trying to use m_Particles.begin() and from what I can tell (by using the debugger) I can't see any values stored in the vector like I could before.
emiel1
emiel1
Is your code the same as the code I listed. If not, please copy/paste your code again. I don't see any errors in my code. Is ParticleEmitter::ParticleEmitter() called?

Emiel
acidic10
acidic10
ParticleEmitter::ParticleEmitter(const Vector3f pPosition, const Vector3f pVelocity, int pNumParticles) : m_Position(pPosition), m_Velocity(pVelocity){    for (int i=0; i<pNumParticles; i++) {        Particle *p = new Particle(Vector3f(100.0f, 100.0f, 100.0f), Vector3f(0.0f, 0.0f, 0.0f), 5, 20);        m_Particles.push_back(p);    }}void ParticleEmitter::emit(){    std::vector<Particle*>::iterator particleIterator;    for (particleIterator = m_Particles.begin(); particleIterator != m_Particles.end(); ++particleIterator) {        (*particleIterator)->move(); // Each particle has a "move" procedure    }}


#ifndef __PARTICLE_EMITTER_H#define __PARTICLE_EMITTER_Hclass ParticleEmitter {    public:            ParticleEmitter();        ParticleEmitter(const Vector3f pPosition, const Vector3f pVelocity, int pNumParticles);        ~ParticleEmitter();                Vector3f getVelocity();        Vector3f getPosition();                void move();        void emit();        void draw();                private:        Vector3f m_Position;        Vector3f m_Velocity;        std::vector<Particle*> m_Particles;};#endif


The constructor is called in main:
    ParticleEmitter *theEmitter = new ParticleEmitter(Vector3f(20.0f, 20.0f, 20.0f), Vector3f(0.0f, 0.0f, 0.0f), 8);


The "emit" procedure is called from a display routine:
	theEmitter->emit();
emiel1
emiel1
Does the number of particles in the vector change when you are initialising the vector? Step through that function with the debugger.
Is Particle *p correctly created? Check that variable with the debugger.
Does any other member function of ParticleEmitter edit and/or remove entries of the vector?
Are some of the entries "delete"d after they are initialised?
KulSeran
KulSeran
You should change your definition to
std::vector< Particle > m_Particles;
There is no reason to have a pointer to each particle, it will kill your performance and means you have to deal with pointer ownership and other nasties.

Then, you could change
Particle *p = new Particle(Vector3f(100.0f, 100.0f, 100.0f), Vector3f(0.0f, 0.0f, 0.0f), 5, 20);m_Particles.push_back(p);

to:
        m_Particles.push_back( Particle(Vector3f(100.0f, 100.0f, 100.0f), Vector3f(0.0f, 0.0f, 0.0f), 5, 20) );

and get rid of all your manual memory managment.
acidic10
acidic10
Quote:
Original post by emiel1
Does the number of particles in the vector change when you are initialising the vector? Step through that function with the debugger.
Does any other member function of ParticleEmitter edit and/or remove entries of the vector?
Are some of the entries "delete"d after they are initialised?


Ok I've stepped through the initialisation of the particles and the push_back into the vector. I breakpointed after it and all of the values are in there and are correct.

The second it hits the line:
    for (particleIterator = m_Particles.begin(); particleIterator != m_Particles.end(); ++particleIterator) {


It gives an access violation error and bombs out. It points to this line in "vector":
 #if _HAS_ITERATOR_DEBUGGING || _SECURE_SCL    iterator begin()        {    // return iterator for beginning of mutable sequence        return (iterator(_Myfirst, this)); <-------- THIS        }


No other member functions currently do anything with the vector or the pointers associated with it.

No entries are being deleted as yet.
emiel1
emiel1
I don't know what the problem is: a testprogram on my computer workes fine. Let's see if changing to instances instead of pointers (KulSeran's solution) workes.
acidic10
acidic10
Quote:
Original post by KulSeran
You should change your definition to
std::vector< Particle > m_Particles;
There is no reason to have a pointer to each particle, it will kill your performance and means you have to deal with pointer ownership and other nasties.

Then, you could change
Particle *p = new Particle(Vector3f(100.0f, 100.0f, 100.0f), Vector3f(0.0f, 0.0f, 0.0f), 5, 20);m_Particles.push_back(p);

to:
        m_Particles.push_back( Particle(Vector3f(100.0f, 100.0f, 100.0f), Vector3f(0.0f, 0.0f, 0.0f), 5, 20) );

and get rid of all your manual memory managment.


I've just done this :) I'm still getting the same problem, though. It bombs out when I try and use m_Particles.begin() :/
acidic10
acidic10
I've figured it out. It was something to do with the actual instance of the ParticleEmitter. Thanks for your help guys! :)
Molle85
Molle85
You can use the following in your constructor to pre-allocate the space needed for your particles before you push them in, so the vector doesn't need to reallocate when dealing with huge number of particles.

this->m_Particles.reserve( pNumParticles );
MaulingMonkey
MaulingMonkey
Quote:
Original post by emiel1
You are creating a vector with pNumParticles with this line:
this->m_Particles = new std::vector<Particle*>(pNumParticles);
These are created as random pointers.

Null pointers, actually, as they are default initialized.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.