Sign in to follow this  

new operator in vector

This topic is 4112 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a vector<Type*> list and for some reason, out of no where for no particular reason at all, in my Add() function: Type* Add() { Type* newType = NULL; newType = new Type(); m_VectorList.push_back(newType); return newType; }; it's giving me an error "Unhandled exception at 0x7c901230 in Phyer Shooter.exe: User breakpoint." actually... correction, sometimes it happens in my Add() fucntion right at the new operator and sometimes it happens in my Remove() at the delete operator. void Remove(long Pos) { std::vector <Type*>::iterator Iter; Iter = m_VectorList.begin() + Pos; if (Iter != m_VectorList.end()) { Type* Ptr = m_VectorList.at(Pos); delete Ptr; Ptr = NULL; m_VectorList.erase(Iter); } }; what's the problem? is does each of these about 50 times a second and sometimes out of no where it will fail at one of those two places.

Share this post


Link to post
Share on other sites
I don't see what is the problem here. it says user breakpoint, so maybe you have a breakpoint enabled in the debugger. Anyway, it is a bad idea to have a vector<Foo*>, because when the vector is destroyed, the objects are not deleted. It can cause huge memory leaks. And even if you delete the objects before deleting the vector, what will happen if an exception occurs and the vector get destroyed.

Instead, you should use a vector of std::auto_ptr or boost shared_ptr, it is more secure, and you can simply use the stl algorithms with your vector.

Share this post


Link to post
Share on other sites
how does an exception occur? what exactly does that mean? and if it does occur, where does the code go and why would my object get deleted even if i code it to do so?

also how does the auto_ptr work? can i see a small example please?

Share this post


Link to post
Share on other sites
Quote:
Original post by DrakeSlayer
Instead, you should use a vector of std::auto_ptr

No, he definatly shouldn't. Copies of std::auto_ptr<>s aren't equivalent, and therefore won't work correctly with vectors (or any of the other containers for that matter).
Quote:
or boost shared_ptr, it is more secure, and you can simply use the stl algorithms with your vector.

Why do you suggest shared ptr? We have no reason to believe his pointers are shared, and if they aren't then the Boost.PointerContainer library would be a much better alternative. Also he might not even want the pointers to be destructed when the container is destroyed, for instance if they are pointing to statically allocated objects, or if some other code has the responsibility of deleting the pointers.

Quote:
also how does the auto_ptr work? can i see a small example please?

Here is a very good (and correct) introduction to std::auto_ptr<>.

The exception could mean many things, when the dialog box comes up is there an "ignore" button? Press it, and then press break. Your IDE will stop and point to the line the exception was thrown at, tell us how this line and the surrounding lines looks like, is it your own code? Also in the call stack (you should be able to find it when you have pressed break) you can see which functions was called prior to the function where the exception occured.

Share this post


Link to post
Share on other sites
ok i'm going to forget about the auto_ptr's then if i don't need to use them.

my code fails at the lines with "new" and "delete" in the code i posted above. I don't see why it would fail when trying to allocate or deallocate memory

Share this post


Link to post
Share on other sites
that's it really:



template <class Type>
class tWVectorList
{
private:
std::vector <Type*> m_VectorList;

public:
Type* Add()
{
Type* newType = NULL;
newType = new Type(); //fails here
m_VectorList.push_back(newType);

return newType;
};
void Remove(long Pos)
{
std::vector <Type*>::iterator Iter;
Iter = m_VectorList.begin() + Pos;
if (Iter != m_VectorList.end())
{
Type* Ptr = m_VectorList.at(Pos);
delete Ptr; // fails here
Ptr = NULL;
m_VectorList.erase(Iter);
}
};
//...
};

Share this post


Link to post
Share on other sites
Quote:
Original post by EvilKnuckles666
that's it really:

*** Source Snippet Removed ***


Well that doesn't fail by itself, I tried a quick test with VS8:
#include <vector>

template <class Type>
class tWVectorList
{
private:
std::vector <Type*> m_VectorList;

public:
Type* Add()
{
Type* newType = NULL;
newType = new Type(); //fails here
m_VectorList.push_back(newType);

return newType;
};
void Remove(long Pos)
{
std::vector <Type*>::iterator Iter;
Iter = m_VectorList.begin() + Pos;
if (Iter != m_VectorList.end())
{
Type* Ptr = m_VectorList.at(Pos);
delete Ptr; // fails here
Ptr = NULL;
m_VectorList.erase(Iter);
}
};
//...
};

int main()
{
tWVectorList<int> s;
s.Add();
s.Add();
s.Remove(0);
}

This ran correctly. Could you please provide us with some actual test showing us a case when it fails (make sure to include everything needed to compile it), then we can investigate what is wrong. You're sure that the error isn't in Type's ctor/dtor right? What is Type when it fails? Does it inherit anything? How does the ctor/dtor look like?

Share this post


Link to post
Share on other sites
well here's the stack:
msvcp71d.dll!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Eos(unsigned int _Newsize=4063232) Line 1475 + 0x22 C++
> msvcr71d.dll!malloc(unsigned int nSize=132) Line 139 + 0x15 C
Phyer Shooter.exe!operator new(unsigned int size=132) Line 12 + 0x9 C++
Phyer Shooter.exe!Wrath2D::cWUtility::tWVectorList<Wrath2D::cWEmitter::sWParticle>::Add() Line 510 + 0xa C++
Phyer Shooter.exe!Wrath2D::cWEmitter::Update(float DeltaTime=0.0020000001) Line 230 + 0x11 C++
Phyer Shooter.exe!Wrath2D::cWEmitter::Draw(float DeltaTime=0.0020000001) Line 365 + 0xc C++
Phyer Shooter.exe!Wrath2D::cWParticleSystem::Render(float DeltaTime=0.0020000001) Line 37 C++
Phyer Shooter.exe!Wrath2D::cWGraphics::Render() Line 229 C++
Phyer Shooter.exe!SDL_main(int argc=1, char * * argv=0x003e5b60) Line 704 C++
Phyer Shooter.exe!_main() + 0xd9 C


cWEmitter::Update()

bool cWEmitter::Update(float DeltaTime)
{
if (SDL_GetTicks() - m_lBirthTime > m_lLifeSpan && m_lLifeSpan != -1 && m_ParticleVList.GetNetItems() == 0)
return false;

sWParticle *Particle = NULL;
long NumtoEmit = 0;

if (SDL_GetTicks() - m_lBirthTime <= m_lLifeSpan || m_lLifeSpan == -1)
NumtoEmit = (long)floorf((SDL_GetTicks() - m_lLastEmit) * (m_pEmitterDef->m_lEmitsPerSec * 1.0f / 1000.0f));

for ( long i=0 ; i<NumtoEmit ; i++)
{
if (m_ParticleVList.GetNetItems() >= (unsigned long)m_pEmitterDef->m_lMaxParticles)
break;

Particle = m_ParticleVList.Add();

// .. Rest of the code only changes Partice's attributes
}
// ...

// then it updates each one
for (unsigned long i=0 ; i<m_ParticleVList.GetNetItems() ; i++)
{
Particle = m_ParticleVList.GetItem((unsigned long)i);

if (SDL_GetTicks() - Particle->m_lBirthTime > Particle->m_lLifeSpan)
{
m_ParticleVList.Remove((unsigned long)i);
i--;
} else {
// if it doesn't need to be removed, it adds physics
}
}




im' thinking it's something to do with in that code as well...

Share this post


Link to post
Share on other sites
This problem almost always occurs not because of the new or delete calls, but because somewhere before the break occurs, you wrote to memory that you shouldn't have. Typically, this occurs by writing past the end of an array, although every once in a while it can also happen with any generic bad pointer.

The reason it happens usually with an array out-of-bounds action is because memory immediately after an array that you own is almost always still valid memory, in the sense that the OS doesn't really know that you shouldn't be writing there. However, with random bad pointers, you usually get a crash immediately, because the memory pointed to is almost always not valid memory, and the OS yells at you for even thinking about writing there.

The reason you only find the problem later on is because when new or delete goes to manage the memory, it uses some of that memory to know how much is allocated and so forth. But one of your invalid writes might have messed up this information. At the time of the write, this was irrelevant; the values were stored in memory, and it didn't matter what those values "meant", or who used them. But when new or delete actually tries to use that memory, it finds horribly incorrect values, and whines and moans. Actually, it wouldn't always whine and moan, because how should it know that the values are actually bad? Conveniently, the debug runtime will go to great lengths to mark memory so that it can figure out when you inappropriately altered memory, and tell you at the at the soonest moment that it realizes you did so, which usually happens when you allocate or deallocate memory. Because it is informing you on purpose, it causes a break to occur, rather than just terminating the program or throwing an exception, for example. This is why it's called a user breakpoint, because it was manually entered by a user. It's a bit confusing, though, because the user that entered it was a runtime-library programmer, not the person actually having the problem.

Check all your array/vector accesses, and make sure that you're not writing past the end of any.

Share this post


Link to post
Share on other sites
What's going on with your Remove function? You're adding Pos to your iterator, and then deleting if it != .end()??? What if Pos pushes it past the end of the vector?

The vector::at() method will do a range check for you, so you could catch any out_of_range exception. The following is faster, though, and avoids this possible 'bug':

void Remove(long Pos)
{
assert(Pos < m_VectorList.size())

std::vector <Type*>::iterator Iter;
Iter = m_VectorList.begin() + Pos;

Type* Ptr = m_VectorList[0];
delete Ptr;
Ptr = NULL;
m_VectorList.erase(Iter);
};


Or if the assert condition is not met, just exit early. Possibly give that a try. As the above post mentions, you are probably accessing memory you shouldn't be accessing.

Share this post


Link to post
Share on other sites
well, i don't think it would be in the Add() because i'm always pushing to the back, but i changed my Remove() to this:

void Remove(long Pos)
{
if (Pos <= m_VectorList.size()) // new code
{
std::vector <Type*>::iterator Iter;
Iter = m_VectorList.begin() + Pos;
if (Iter != m_VectorList.end())
{
Type* Ptr = m_VectorList.at(Pos);
delete Ptr;
Ptr = NULL;
m_VectorList.erase(Iter);
}
}
};




edit: I just put that in and it no longer fails in my Remove() anymore, now it's all in my Add() all the time... what's wrong with push_back()??? can it ever fail like that or what?

Share this post


Link to post
Share on other sites
Quote:
Original post by EvilKnuckles666
well, i don't think it would be in the Add() because i'm always pushing to the back, but i changed my Remove() to this:
*** Source Snippet Removed ***

edit: I just put that in and it no longer fails in my Remove() anymore, now it's all in my Add() all the time... what's wrong with push_back()??? can it ever fail like that or what?


See my post above. Your problem is almost certainly not in Add(), but elsewhere in your program.

Share this post


Link to post
Share on other sites
Quote:
Original post by EvilKnuckles666
how would i find that though if it doesn't break in the right point? i've traced it back through just about every instance where i add and remove and id on't see what's wrong with it...


You'd probably need to examine your code manually, and look for places where you access elements in an array. Check to make sure that it is absolutely impossible at those times to access elements beyond the array. You may have to manually calculate what indexes you use to access an array, manually walk through loops in your mind, and so forth. Just gotta make sure that it is 100% impossible to access invalid elements.

Share this post


Link to post
Share on other sites

This topic is 4112 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this