how to check if a pointer is unbound?

J

Jess

Hello,

I tried a program as follows:

include<iostream>

using namespace std;

class A{
public:
int x;
A():x(10){}
};

int main(){
A a;
A* p = &a;
A* q = p;
delete p;
cout << q << endl;
return 0;
}

Since "q" should be unbound, I thought the output would be "0".
However, the result was segmentation fault. How can I check if a
pointer is unbound?

Thanks,
Jess
 
Z

Zeppe

Jess said:
Since "q" should be unbound, I thought the output would be "0".
However, the result was segmentation fault. How can I check if a
pointer is unbound?

You can't, in a standard way. But you can use safer approached as
smart-pointers.

Regards,

Zeppe
 
R

Ron Natalie

Jess said:
Since "q" should be unbound, I thought the output would be "0".
However, the result was segmentation fault. How can I check if a
pointer is unbound?
No. It is up to the programmer to manage pointers. Any access
to pointer value previously passed to delete is undefined. Anything
can happen from segmentation fault to apparently working normally.

Delete takes an rvalue, it can not change it's operanrd.

There's no way to test whether a pointer is bound.

If you wish to keep the pointer around and need to flag that
it has been deleted, the common way is to set the variable to
the null pointer (0).
 
F

Fred Kleinschmidt

Ron Natalie said:
No. It is up to the programmer to manage pointers. Any access
to pointer value previously passed to delete is undefined. Anything
can happen from segmentation fault to apparently working normally.

Delete takes an rvalue, it can not change it's operanrd.

There's no way to test whether a pointer is bound.

If you wish to keep the pointer around and need to flag that
it has been deleted, the common way is to set the variable to
the null pointer (0).

That will not work. You removed the relevant part of the OP's post:
int main(){
A a;
A* p = &a;
A* q = p;
delete p;
cout << q << endl;
return 0;
}


So, what happens if he adds
p=NULL;
after deleting p?

He still has the same problem, since he is trying to use /q/, not /p/
And it it is not reasonable for you to say that he should set q=NULL
too. These may occur in different modules, and when he deletes p,
there is no way for that module to know whether other pointers have
been set to point to the same place as p.
 
H

Howard

Fred Kleinschmidt said:
That will not work. You removed the relevant part of the OP's post:
int main(){
A a;
A* p = &a;
A* q = p;
delete p;
cout << q << endl;
return 0;
}


So, what happens if he adds
p=NULL;
after deleting p?

He still has the same problem, since he is trying to use /q/, not /p/
And it it is not reasonable for you to say that he should set q=NULL
too. These may occur in different modules, and when he deletes p,
there is no way for that module to know whether other pointers have
been set to point to the same place as p.
--

I don't see anywhere that Victor said setting p to NULL would solve the
problem in that specific example. He just said that the common way to know
that a pointer has been passed to delete was to set it to NULL (after
calling delete). That's true.

In the specific example, he could also set q=NULL. (And then check it
before calling cout.)

If one wants to address a more complex case than that silly example, then
the answer is still the same, really. It's up to the program[mer] to keep
track of whether any pointer has been deleted or not. And one way to do
that is to set it to NULL.

If you're setting multiple pointers to point to a given object, then
*somewhere* you need to keep that information stored. That may be in a
reference-counted pointer, but it may not. After all, you may *want* the
object completely destroyed when passing any one of the pointers to it to
delete, (whereas a reference-counted solution would keep it alive until the
last pointer to it was passed to delete).

One solution would be to create another object which owns the original
object, and which hands out values to the pointers, and keeps track of which
pointers have been given values. Then, when the owning object is deleted,
it deletes the owned object, and also loops through all the pointers it has
assigned values to, and assigns NULL to them.

In any case, someone needs to *explicitly* keep track of the validity of the
pointer, because it can't do the job for you.

-Howard
 
R

Richard Herring

Nobody seems to have pointed out that he's already in terminal trouble,
since what p pointed to wasn't created by new in the first place :-(
He still has the same problem, since he is trying to use /q/, not /p/
And it it is not reasonable for you to say that he should set q=NULL
too. These may occur in different modules, and when he deletes p,
there is no way for that module to know whether other pointers have
been set to point to the same place as p.

I don't see anywhere that Victor said setting p to NULL would solve the
problem in that specific example. He just said that the common way to know
that a pointer has been passed to delete was to set it to NULL (after
calling delete). That's true.

In the specific example, he could also set q=NULL. (And then check it
before calling cout.)

If one wants to address a more complex case than that silly example, then
the answer is still the same, really. It's up to the program[mer] to keep
track of whether any pointer has been deleted or not. And one way to do
that is to set it to NULL.

If you're setting multiple pointers to point to a given object, then
*somewhere* you need to keep that information stored. That may be in a
reference-counted pointer, but it may not. After all, you may *want* the
object completely destroyed when passing any one of the pointers to it to
delete, (whereas a reference-counted solution would keep it alive until the
last pointer to it was passed to delete).

One solution would be to create another object which owns the original
object, and which hands out values to the pointers, and keeps track of which
pointers have been given values. Then, when the owning object is deleted,
it deletes the owned object, and also loops through all the pointers it has
assigned values to, and assigns NULL to them.

In any case, someone needs to *explicitly* keep track of the validity of the
pointer, because it can't do the job for you.

-Howard
 
R

red floyd

Jess said:
Hello,

I tried a program as follows:

include<iostream>

using namespace std;

class A{
public:
int x;
A():x(10){}
};

int main(){
A a;
A* p = &a;
A* q = p;
delete p;
At this point anything can happen. "delete p" causes Undefined
Behavior, as p was *NOT* allocated on the free store. Any questions
about what happens next has no valid answer, other than "anything can
happen".
cout << q << endl;
return 0;
}

Since "q" should be unbound, I thought the output would be "0".
However, the result was segmentation fault. How can I check if a
pointer is unbound?


See above.
 
R

red floyd

Richard said:
Nobody seems to have pointed out that he's already in terminal trouble,
since what p pointed to wasn't created by new in the first place :-(

I caught it :), but I hadn't read the rest of this thread yet.
 
J

Jess

In message <[email protected]>,





Nobody seems to have pointed out that he's already in terminal trouble,
since what p pointed to wasn't created by new in the first place :-(




I don't see anywhere that Victor said setting p to NULL would solve the
problem in that specific example. He just said that the common way to know
that a pointer has been passed to delete was to set it to NULL (after
calling delete). That's true.
In the specific example, he could also set q=NULL. (And then check it
before calling cout.)
If one wants to address a more complex case than that silly example, then
the answer is still the same, really. It's up to the program[mer] to keep
track of whether any pointer has been deleted or not. And one way to do
that is to set it to NULL.
If you're setting multiple pointers to point to a given object, then
*somewhere* you need to keep that information stored. That may be in a
reference-counted pointer, but it may not. After all, you may *want* the
object completely destroyed when passing any one of the pointers to it to
delete, (whereas a reference-counted solution would keep it alive until the
last pointer to it was passed to delete).
One solution would be to create another object which owns the original
object, and which hands out values to the pointers, and keeps track of which
pointers have been given values. Then, when the owning object is deleted,
it deletes the owned object, and also loops through all the pointers it has
assigned values to, and assigns NULL to them.
In any case, someone needs to *explicitly* keep track of the validity of the
pointer, because it can't do the job for you.

Right, I forgot I can't delete statically allocated object! :)
 
J

Jess

One solution would be to create another object which owns the original
object, and which hands out values to the pointers, and keeps track of which
pointers have been given values. Then, when the owning object is deleted,
it deletes the owned object, and also loops through all the pointers it has
assigned values to, and assigns NULL to them.

I know how to keep a reference count, but can you please show me how
the owner of the object can keep track of which pointers are pointing
to the object and set all of them to NULL when the object is
destroyed?

Thanks,
Jess
 
J

James Kanze

I know how to keep a reference count, but can you please show me how
the owner of the object can keep track of which pointers are pointing
to the object and set all of them to NULL when the object is
destroyed?

It's called the Observer pattern. A simple version of it is
used boost::weak_ptr, and an even simpler version in my
ManagedPtr. More generally, however, any object "interested" in
your object registers as an observer, and you inform all
interested objects in the destructor that you're no longer
available. The interested objects then take whatever steps they
deem appropriate: it can be as simple as nulling a pointer, but
will more often (in my experience) involve removing the pointer
from a set or a map, or even obtaining alternative resources or
changing it's own internal state.
 
R

Ron Natalie

I don't see anywhere that Victor said setting p to NULL would solve the
problem in that specific example.

Don't call me Victor (even if we are more or less interchangable).
 
J

Jess

It's called the Observer pattern. A simple version of it is
used boost::weak_ptr, and an even simpler version in my
ManagedPtr. More generally, however, any object "interested" in
your object registers as an observer, and you inform all
interested objects in the destructor that you're no longer
available.

So an "interested" object (call it A) should have a field to indicate
whether the object it's interested in (call it B) is still available
and this field can be set (possibly via some function of A)?
The interested objects then take whatever steps they
deem appropriate:

Should the interested object (A) take this action as soon as it sees
the object (B) is destroyed, or, at some other time (e.g. when A is
about to use B)?
it can be as simple as nulling a pointer, but
will more often (in my experience) involve removing the pointer
from a set or a map,

Does this set or map store all the pointers it has that point to the
external objects (including B here)?

Many thanks,
Jess
 
J

James Kanze

So an "interested" object (call it A) should have a field to indicate
whether the object it's interested in (call it B) is still available
and this field can be set (possibly via some function of A)?

Maybe. One of the most frequent uses of pointers is navigation.
If there is a one to n relationship, the object on the one side
will typically have a container with the pointers. The call
back for "object deleted" just removes the pointer from the
container: no flags, no extra pointers, no nothing.
Should the interested object (A) take this action as soon as it sees
the object (B) is destroyed, or, at some other time (e.g. when A is
about to use B)?

Normally, as soon as it is notified of the destruction.
Otherwise, it has to set a flag of some sort, and test it later.
Does this set or map store all the pointers it has that point to the
external objects (including B here)?

Maybe. It depends on the design. An object doesn't contain a
pointer to another object just for the fun of having pointers to
manage. It contains the pointer for a specific purpose,
according to the design of the application. What it should do
if the object in question is destructed depends on the design,
the role of the two objects in that design, and the relationship
between the objects. It's very application specific.
 
J

Jess

Maybe. One of the most frequent uses of pointers is navigation.
If there is a one to n relationship, the object on the one side
will typically have a container with the pointers. The call
back for "object deleted" just removes the pointer from the
container: no flags, no extra pointers, no nothing.

The message that the object has been deleted must be passed on to the
owner of pointer container. Do you think a possible way is to
implement member function of the owner of the container, so that this
function can be called when a object is deleted?

Thanks,
Jess
 
J

James Kanze

The message that the object has been deleted must be passed on to the
owner of pointer container. Do you think a possible way is to
implement member function of the owner of the container, so that this
function can be called when a object is deleted?

Of course. This is a classical example of the observer pattern.
 
J

JohnQ

Jess said:
Hello,

I tried a program as follows:

include<iostream>

using namespace std;

class A{
public:
int x;
A():x(10){}
};

int main(){
A a;
A* p = &a;
A* q = p;
delete p;
cout << q << endl;
return 0;
}

Since "q" should be unbound, I thought the output would be "0".
However, the result was segmentation fault. How can I check if a
pointer is unbound?

Why doesn't/can't C++ set deleted pointers (and freed memory pointers
therefor) to null? It would seem that dereferencing a null pointer and
getting an exception is preferable than dereferencing and REusing a ptr and
not noticing that it had already been freed/deleted. (I know this has been
asked and answered before, but I forgot what the short answer is).

John
 
A

Alf P. Steinbach

* JohnQ:
Why doesn't/can't C++ set deleted pointers (and freed memory pointers
therefor) to null? It would seem that dereferencing a null pointer and
getting an exception is preferable than dereferencing and REusing a ptr and
not noticing that it had already been freed/deleted. (I know this has been
asked and answered before, but I forgot what the short answer is).

C++ doesn't force that inefficiency on you, but it allows you to easily
define that functionality yourself if you want it:

template< typename T >
void destroy( T*& p ) { delete p; p = 0; }

(plus more overloads plus destroyArray).

It isn't necessarily a good idea.

The problem is that by relying on defined behavior that defined behavior
may easily be abused, resulting in nullpointer-checks everywhere.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,294
Messages
2,571,511
Members
48,201
Latest member
JefferyBur

Latest Threads

Top