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! ] 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.
"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
> 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! ]
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
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! ]
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! ]
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
> 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! ]
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! ] This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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
{
|
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?
|
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...
|
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>);
|
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:
| |
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...
|
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:
|
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
|
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...
|
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...
|
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...
| |
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...
|
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...
|
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();...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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
| |
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...
| |