473,659 Members | 3,475 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Deleting Pointers from STL Vector

I'm iterating over a vector of base class pointers and deleting those
which meet a certain criteria...i'm using pretty text-book code for
the particular delete/erasure (it's straight out of Myers' Effective
STL), and reads like this:

void CGame::RemoveDe adObjects()
{
// cleanup crew!!
vector<CDrawabl eObject*>::iter ator i;

for (i = g_vecGameObject s.begin(); i !=
g_vecGameObject s.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject * toDie = *i;

// erase...
i = g_vecGameObject s.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
}
else
++i;
}
}

Here's the problem: on the two lines that say delete toDie; toDie =
NULL; I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.

In other words, if one of the CDrawableObject s* was say, a member var
of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:

1. Before the delete, toDie and m_cdPlayer1 have a value of
0x00a72498.

2. After the delete, both toDie and m_cdPlayer1 have their __vfptr
point to memory 0xFEEEFEEE (signifying a delete)

3. After the set-to-null, the value of toDie becomes 0x00000000, while
m_cdPlayer1 remains at a value of 0x00a72498 (while still pointing to
0xFEEEFEEE).

Not the behavior I want. At this point, m_cdPlayer1 is officially
deleted, yet the test "if (m_cdPlayer)" fails, since it is technically
not NULL.

Any suggestions or recommendations on how to get the intended behavior
out of this snippet?

- Hanzo

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Jul 19 '05 #1
20 12979
[Cross-post to moderated group removed. I'd rather not wait for
moderation. Generally, you should not cross-post to moderated groups.]

Hanzo wrote:
I'm iterating over a vector of base class pointers and deleting those
which meet a certain criteria...i'm using pretty text-book code for
the particular delete/erasure (it's straight out of Myers' Effective
STL), and reads like this:

void CGame::RemoveDe adObjects()
{
// cleanup crew!!
vector<CDrawabl eObject*>::iter ator i;

for (i = g_vecGameObject s.begin(); i !=
g_vecGameObject s.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject * toDie = *i;

// erase...
i = g_vecGameObject s.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
Why bother setting this to NULL when it's about to go out of scope and
cease to exist?

Also, there would be nothing wrong with doing this instead:

delete *i;
i = g_vecGameObject s.erase(i);
}
else
++i;
}
}

Here's the problem: on the two lines that say delete toDie; toDie =
NULL; I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.
The original variable to which toDie was pointing is gone. It doesn't
exist. You deleted it. Once you've done that, you have no business
attempting to determine its value.

In other words, if one of the CDrawableObject s* was say, a member var
of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:
You are saying you have two different, unrelated pointers pointing to
the same dynamically created object? In that case, your problem is poor
design. The solution is to fix the design.

1. Before the delete, toDie and m_cdPlayer1 have a value of
0x00a72498.

2. After the delete, both toDie and m_cdPlayer1 have their __vfptr
point to memory 0xFEEEFEEE (signifying a delete)
I don't know what a __vfptr is, but pointers are just pointer - they
don't "have" anything called __vfptr. Theoretically, they could point to
something that does, but in this case you have deleted the thing they
point to, so you may not examine it or attempt to determine its value in
any way. If you do so, your program's behavior is undefined.

3. After the set-to-null, the value of toDie becomes 0x00000000, while
m_cdPlayer1 remains at a value of 0x00a72498 (while still pointing to
0xFEEEFEEE).
Of course.

Not the behavior I want. At this point, m_cdPlayer1 is officially
deleted, yet the test "if (m_cdPlayer)" fails, since it is technically
not NULL.
Of course.

Any suggestions or recommendations on how to get the intended behavior
out of this snippet?


Don't share an object between two pointers like that. Or, if you do,
have one pointer "own" the object - never attempt to delete it through
the other pointer. This can get complicated, though. You have to be sure
the owner doesn't delete it while it may still be accessed through any
other pointer.

In general, you cannot know whether the object pointed to by a pointer
still exists, or has been deleted, and any attempt to refer to a deleted
object causes undefined behavior.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #2
"Hanzo" <ha***@milclan. com> wrote in message
news:om******** *************** *********@4ax.c om...
http://www.cuj.com/documents/s=8890/...p0310alexandr/
[...]
Any suggestions or recommendations on how to get the intended behavior
out of this snippet?


Yes. Use a smart pointer. Then, just destroy the copies of pointers that
you don't want any more. When the last pointer to the object is destroyed,
the object will be freed. Here's a pretty popular smart pointer:

www.boost.org/libs/smart_ptr/index.htm

Dave

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.521 / Virus Database: 319 - Release Date: 9/23/2003
Jul 19 '05 #3
> I'm iterating over a vector of base class pointers and deleting those
which meet a certain criteria...i'm using pretty text-book code for
the particular delete/erasure (it's straight out of Myers' Effective
STL), and reads like this:

void CGame::RemoveDe adObjects()
{
// cleanup crew!!
vector<CDrawabl eObject*>::iter ator i;

for (i = g_vecGameObject s.begin(); i !=
g_vecGameObject s.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject * toDie = *i;

// erase...
i = g_vecGameObject s.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
}
else
++i;
}
}

Here's the problem: on the two lines that say delete toDie; toDie =
NULL;
After those lines toDie runs out of scope; why bother setting it to
NULL?
I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.


'toDie = NULL;' only sets the toDie pointer to NULL it does not affect
the object it was pointing to. Note that that object no longer exists at
the point toDie is being set to NULL because it was deleted just before
that line.

--
Peter van Merkerk
peter.van.merke rk(at)dse.nl

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Jul 19 '05 #4
On Thu, 02 Oct 2003 18:58:44 GMT, Kevin Goodsell
<us************ *********@never box.com> wrote:
[Cross-post to moderated group removed. I'd rather not wait for
moderation. Generally, you should not cross-post to moderated groups.]
Sorry about that.
Why bother setting this to NULL when it's about to go out of scope and
cease to exist?
The goal is to have m_cdPlayer1 set to NULL; my only access to it at
that point is via an iterator walking the g_vecGameObject s vector,
though.
delete *i;
i = g_vecGameObject s.erase(i);


Several people have recommended this strategy now, I just want to make
sure that, ultimately, m_cdPlayer1 is the variable that is deleted/set
to NULL, so that later on in the code, when I need to perform this
check:

if (m_cdPlayer != NULL)

That I don't erroneously evaluate to true when in fact the variable
has been deleted and *should* be NULL.

- Hanzo

Jul 19 '05 #5
Hanzo <ha***@milclan. com> wrote in message news:<om******* *************** **********@4ax. com>...
I'm iterating over a vector of base class pointers and deleting those
which meet a certain criteria...i'm using pretty text-book code for
the particular delete/erasure (it's straight out of Myers' Effective
STL), and reads like this:

void CGame::RemoveDe adObjects()
{
// cleanup crew!!
vector<CDrawabl eObject*>::iter ator i;

for (i = g_vecGameObject s.begin(); i !=
g_vecGameObject s.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject * toDie = *i;
Here toDie is a COPY of the pointer referenced by the iterator i.
When you later set toDie to NULL (and why not just 0?) you are only
setting that copy, and of course not the original pointer it was
copied from.

All you need to do is to make toDie be a reference to the pointer of
interest, rather than a copy of it. Simply change the above
declaration to:

CDrawableObject * &toDie = *i;

and all will work as you expect.

Randy.

// erase...
i = g_vecGameObject s.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
}


{ Snip of unreferenced quoting. -mod/jep }

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Jul 19 '05 #6
Hanzo <ha***@milclan. com> wrote in message news:<om******* *************** **********@4ax. com>...
I'm iterating over a vector of base class pointers and deleting those
which meet a certain criteria...i'm using pretty text-book code for
the particular delete/erasure (it's straight out of Myers' Effective
STL), and reads like this:

void CGame::RemoveDe adObjects()
{
// cleanup crew!!
vector<CDrawabl eObject*>::iter ator i;

for (i = g_vecGameObject s.begin(); i !=
g_vecGameObject s.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject * toDie = *i;

// erase...
i = g_vecGameObject s.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
}
else
++i;
}
}

Here's the problem: on the two lines that say delete toDie; toDie =
NULL; I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.

In other words, if one of the CDrawableObject s* was say, a member var
of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:

1. Before the delete, toDie and m_cdPlayer1 have a value of
0x00a72498.

2. After the delete, both toDie and m_cdPlayer1 have their __vfptr
point to memory 0xFEEEFEEE (signifying a delete)

3. After the set-to-null, the value of toDie becomes 0x00000000, while
m_cdPlayer1 remains at a value of 0x00a72498 (while still pointing to
0xFEEEFEEE).

Not the behavior I want. At this point, m_cdPlayer1 is officially
deleted, yet the test "if (m_cdPlayer)" fails, since it is technically
not NULL.

Any suggestions or recommendations on how to get the intended behavior
out of this snippet?


Put boost::shared_p trs in your vector (no delete needed, just erase
from the vector), and use boost::weak_ptr as m_cdPlayer1. That should
do what you want.

http://www.boost.org.

Bob

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Jul 19 '05 #7
On 2 Oct 2003 19:44:52 -0400, rm*****@isicns. com (Randy Maddox) wrote:
Hanzo <ha***@milclan. com> wrote in message news:<om******* *************** **********@4ax. com>...
All you need to do is to make toDie be a reference to the pointer of
interest, rather than a copy of it. Simply change the above
declaration to:

CDrawableObject * &toDie = *i;

and all will work as you expect.


This does not work.

1. toDie is set to 0x00000000 after the delete and assignment to NULL.
m_cdPlayer1, while pointing to 0xFEEEFEEE, is still a value of
0x00a72498. This evaluates to not NULL, and fails a test to see if it
exists.

2. Some other people have suggested I do this:

if ((*i) && (*i)->CanRemove())
{
delete *i;
*i = NULL;

This, also, does not work. After the delete, both *i and m_cdPlayer1
point to 0xFEEEFEEE (deleted), and their values are both 0x00a72498.
However, after *i is assigned to NULL, its value is 0x00000000, while
m_cdPlayer1 remains 0x00a72498.

Ultimately, this boils down to one fact: I absolutely need a way to
walk a vector of base pointers, and delete/NULL them, affecting the
original variables that were pushed onto the vector in the first
place.

Some people have also suggested smart pointers and boost, and I am
stuck with STLPort. Sorry.

- Hanzo
Jul 19 '05 #8
> void CGame::RemoveDe adObjects()
{
// cleanup crew!!
vector<CDrawabl eObject*>::iter ator i;

for (i = g_vecGameObject s.begin(); i !=
g_vecGameObject s.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject * toDie = *i;

// erase...
i = g_vecGameObject s.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
}
else
++i;
}
}

Here's the problem: on the two lines that say delete toDie; toDie =
NULL; I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.
Yes, because you "delete" the object both "toDie" and your vector
element points to, but modify only the (automatic) poiter "toDie". As
usual with pointers, there's a difference between the pointer and the value /
instance it points to. So it has not much to do with "std::vecto r<>" nor with
C++.
In other words, if one of the CDrawableObject s* was say, a member var
of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:
Do you mean, that "m_cdPlayer 1" is an instance, not a pointer? If so, you
cannot achieve your goal. So "m_cdPlayer 1" _must_ be a pointer.
Any suggestions or recommendations on how to get the intended behavior
out of this snippet?


The misconception is, that "vector<CDrawab leObject*>" is the wrong type for
your usage. You should store pointers to (member) pointers instead like this:
"vector< CDrawableObject s *CGame::* > v;"
Now "delete myGame.*v[42]; myGame.*v[42]=0;"
will do the trick.

In other words, you need one further indirection in addressing.

Cheers,
Philipp.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Jul 19 '05 #9
Hanzo wrote:
I'm iterating over a vector of base class pointers and deleting those
which meet a certain criteria...i'm using pretty text-book code for
the particular delete/erasure (it's straight out of Myers' Effective
STL), and reads like this:

void CGame::RemoveDe adObjects()
{
// cleanup crew!!
vector<CDrawabl eObject*>::iter ator i;

for (i = g_vecGameObject s.begin(); i !=
g_vecGameObject s.end();)
{
// if object is not null and can be removed...
if ((*i) && (*i)->CanRemove())
{
// grab hold before erasure
CDrawableObject * toDie = *i;

// erase...
i = g_vecGameObject s.erase(i);

// ...and kill
delete toDie;
toDie = NULL;
}
else
++i;
}
}

Here's the problem: on the two lines that say delete toDie; toDie =
NULL; I am noticing that the original variable to which toDie is
pointing is not being set to NULL, just "toDie" itself.

In other words, if one of the CDrawableObject s* was say, a member var
of CGame called m_cdPlayer1, when the delete/set-to-NULL happens:

1. Before the delete, toDie and m_cdPlayer1 have a value of
0x00a72498.

2. After the delete, both toDie and m_cdPlayer1 have their __vfptr
point to memory 0xFEEEFEEE (signifying a delete)

3. After the set-to-null, the value of toDie becomes 0x00000000, while
m_cdPlayer1 remains at a value of 0x00a72498 (while still pointing to
0xFEEEFEEE).

Not the behavior I want. At this point, m_cdPlayer1 is officially
deleted, yet the test "if (m_cdPlayer)" fails, since it is technically
not NULL.

Any suggestions or recommendations on how to get the intended behavior
out of this snippet?


Try working with vector<CDrawabl eObject **>. This has enough
indirection to give you the "desired" effect. You'll need to
write:

delete *toDie;
*toDie = NULL;
Having said that, the real problem appears to be a misunderstandin g
of pointers and indirection.

The variable toDie is a local variable, the assignment 'toDie = NULL'
merely sets that variable to NULL. A different variable, of the
same type and value (m_cdPlayer) is not affected at all. However,
due to the interpretation of the type (pointer to CDrawableObject ),
and the statement 'delete toDie;' the variable m_cdPlayer holds a
value that is no longer valid.

The expectation that 'toDie = NULL' will affect any other variable,
under the conditions stated above, indicates a misunderstandin g of
pointer indirection and iterators.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Jul 19 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
3562
by: Xamalek | last post by:
Greetings, I have a question. When using an STL container, does deleting a container of pointers also call delete on the (contained) pointers? For example, if I have (ignore the fluff, it is simply used to explain my issue) struct Proc {
14
3522
by: Roland Bengtsson | last post by:
I have a class Conception and I have this in a vector, it should be: vector<Conception> vek; // vector vector<Conception>::iterator vek; // iterator to vek But what if I want to have pointers to class Conception instead? How can I do that? And how should I write to declare an iterator to this vector?
9
1880
by: Aguilar, James | last post by:
Hey guys. A new question: I want to use an STL libarary to hold a bunch of objects I create. Actually, it will hold references to the objects, but that's beside the point, for the most part. Here's the question: I want to be able to change the references (including deleting them). Is there any way to do that besides using pointers rather than references for the STL library? I'd also prefer to avoid using const_cast, if it is indeed...
5
2758
by: edward.birch | last post by:
Can anyone see anything wrong with the following code? (CONTAINER can be list, vector, set, ...) template <class T> void Destroy(T * p) { delete p; } void CleanUp(std::CONTAINER<ContainerType *> & Container) { std::foreach(Container.begin(), Container.end(), Destroy<ContainerType>);
5
2770
by: FefeOxy | last post by:
Hi, > I'm having a debug assertion error within the file dbgdel.cpp with the expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) I traced the origin of the error and it happened as I tried to delete a polymorphic class as follows:
7
2238
nabh4u
by: nabh4u | last post by:
hi, i have a double linked list containing some elements and i have a vector which stores the address of the elements in the list (pointer to the list). i want to delete a value from the list,like the nth value enetered in the list, in constant time. how do i do that? i got the address of the element to be deleted from the vector but how do i relate that address with the element in the list and then delete it and rearrange the pointers for the...
6
3993
by: Jia | last post by:
Hi all, I have a class foo which has a static vector of pointers of type base class, and a static function to set this vector. #include <iostream> #include <vector> using namespace std; class super{ protected:
4
3503
by: Josefo | last post by:
Hello, is someone so kind to tell me why I am getting the following errors ? vector_static_function.c:20: error: expected constructor, destructor, or type conversion before '.' token vector_static_function.c:21: error: expected constructor, destructor, or type conversion before '.' token
3
2665
by: deepak1905 | last post by:
Hi, I am working on c++ in a linux system ( Fedora core 4 ), kernel version - 2.6.11-1.1369_FC4 gcc version - 4.0.0 20050519 ( Red Hat 4.0.0-8 ) In my code i am creating a vector to store pointers of type structure "SAMPLE_TABLE_STRUCT" ( size of this structure is 36 bytes ). I create an instance of structure "SAMPLE_TABLE_STRUCT" using operator "new" and push back into the vector,this is done inside a for loop for 204800 times. After i...
0
8851
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8748
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
7359
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6181
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5650
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4175
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4335
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2754
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1739
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.