By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,743 Members | 1,058 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,743 IT Pros & Developers. It's quick & easy.

Does malloc() reuse addresses?

P: n/a
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.

Jul 14 '06 #1
Share this Question
Share on Google+
48 Replies


P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11*********************@h48g2000cwc.googlegro ups.com...
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc().
Yes. It happens all the time.
Jul 14 '06 #2

P: n/a
"avasilev" <al********@gmail.comwrites:
if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc().
Yes.
I would like to have confirmation on whether this is
practically a concern when pointers are used to uniquely
identify data structure instances - like in this example:
It's an incorrect approach. Strictly speaking the behavior of
doing anything with a pointer to freed memory yields undefined
behavior.

You're better off using a counter to stamp each new structure
with a unique serial number and then comparing those unique
serial numbers.
--
"We put [the best] Assembler programmers in a little glass case in the hallway
near the Exit sign. The sign on the case says, `In case of optimization
problem, break glass.' Meanwhile, the problem solvers are busy doing their
work in languages most appropriate to the job at hand." --Richard Riehle
Jul 14 '06 #3

P: n/a

avasilev wrote:
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc().
It might; you cannot depend on it though.
I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.
yes

goose,

Jul 14 '06 #4

P: n/a


shouldnt be a problem, because if you're really keeping track of valid
pointers with that table, anytime you do a free() on a pointer you MUST
be removing that entry from the table.

Jul 14 '06 #5

P: n/a
On 14 Jul 2006 11:48:15 -0700, "avasilev" <al********@gmail.com>
wrote:
>Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
All in all a terrible plan.

Once an area of memory is freed, the pointer that was passed to free
becomes indeterminate so any attempt to evaluate that pointer invokes
undefined behavior.

Attempting to use the coincidence is extremely non-portable. Even if
the addresses should match up, how do you know that someone else did
not use (and free) the area in between the time you freed and
allocated it again. In a virtual memory system, even if the address
is the same it may be in a physically different portion of memory.
Some OSes reinitialize allocated memory (not necessarily to zero) as a
security precaution before allowing me to use it.
Remove del for email
Jul 14 '06 #6

P: n/a

avasilev wrote:
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.
If you are doing what you say with the instance array, why are you not
removing the pointer from the array when you free the element of the
list. Sounds like you might want to rethink your design a little.

Jul 14 '06 #7

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11*********************@h48g2000cwc.googlegro ups.com...

What (exactly) are you trying to accomplish? Maybe if we knew what it was,
we could offer a suitable and portable method of accomplishing it.
Jul 14 '06 #8

P: n/a

Ancient_Hacker wrote:
shouldnt be a problem, because if you're really keeping track of valid
pointers with that table, anytime you do a free() on a pointer you MUST
be removing that entry from the table.
Yes, but later I can allocate a new pointer and add it to the table, it
could happen to have the same value. Then a previously non-vaid pointer
becomes valid now.

Jul 14 '06 #9

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11*********************@m79g2000cwm.googlegro ups.com...
>
Ancient_Hacker wrote:
>shouldnt be a problem, because if you're really keeping track of valid
pointers with that table, anytime you do a free() on a pointer you MUST
be removing that entry from the table.

Yes, but later I can allocate a new pointer and add it to the table, it
could happen to have the same value. Then a previously non-vaid pointer
becomes valid now.
But it does not necessarily even point to the same kind of object.

Some other malloc(), even inside a library call or DLL or some such thing,
may have allocated memory at that starting address. And if it has not been
allocated even testing to see what the value is invokes undefined behavior.

We can say for sure:

Broken plan, don't do it.

Really, really. Don't.
Jul 14 '06 #10

P: n/a

avasilev wrote:
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.


Ok I will clarify this a bit, sice some people did not get it properly.
I have a list of instance pointers. Every allocated instance is added
to this list and every freed instance is immediately removed from
there. The problem is that copies of these pointers need to be passed
around, and it may happen that when such a copy has to be used, the
instance it points to may be already gone. So a way to validate the
pointer is needed - and this pointer comparison approach was chosen -
not by me, I am kindof revising the thing. So my question was to
confirm how reliable is the current verification mechanism. My opinion
is that it is not, since pointer values for different instances (in
time) may conicide.

Jul 14 '06 #11

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11**********************@m79g2000cwm.googlegr oups.com...
>
avasilev wrote:
>Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.

Ok I will clarify this a bit, sice some people did not get it properly.
I have a list of instance pointers. Every allocated instance is added
to this list and every freed instance is immediately removed from
there. The problem is that copies of these pointers need to be passed
around, and it may happen that when such a copy has to be used, the
instance it points to may be already gone. So a way to validate the
pointer is needed - and this pointer comparison approach was chosen -
not by me, I am kindof revising the thing. So my question was to
confirm how reliable is the current verification mechanism. My opinion
is that it is not, since pointer values for different instances (in
time) may conicide.
If you know for sure that:
1. The pointers in your list are valid pointers (all the bad ones, having
been removed)
2. The pointers in your list point to the appropriate data type

You still have a problem.

Suppose that pointer 0xdeadbeef is some valid "bucket of chicken" pointer in
your list. You assign that pointer to some struct in memory and say,
"Here's your bucket of chicken."
Later on, the pointer 0xdeadbeef gets freed. Now, we have this pointer,
0xdeadbeef and we want to know if it is valid. If we examine our "bucket of
chicken" pointer and say:
pointer 0 in the list is 0xc0ffc0ff. Is pointer 0xc0ffc0ff equal to pointer
0xdeadbeef?

The simple act of examining the contents of the pointer that is storing
0xdeadbeef invokes undefined behavior. Your computer could dump core, or
Scott Nudds could come flying out of your left nostril. Really, it's
practically in the standard. At least comp.std.c made a similar remark
concerning demons some time ago.

Jul 14 '06 #12

P: n/a

Dann Corbit wrote:
"avasilev" <al********@gmail.comwrote in message
news:11**********************@m79g2000cwm.googlegr oups.com...

avasilev wrote:
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.
Ok I will clarify this a bit, sice some people did not get it properly.
I have a list of instance pointers. Every allocated instance is added
to this list and every freed instance is immediately removed from
there. The problem is that copies of these pointers need to be passed
around, and it may happen that when such a copy has to be used, the
instance it points to may be already gone. So a way to validate the
pointer is needed - and this pointer comparison approach was chosen -
not by me, I am kindof revising the thing. So my question was to
confirm how reliable is the current verification mechanism. My opinion
is that it is not, since pointer values for different instances (in
time) may conicide.

If you know for sure that:
1. The pointers in your list are valid pointers (all the bad ones, having
been removed)
2. The pointers in your list point to the appropriate data type

You still have a problem.
No no, Im no examining the moemory that hte pointer points to, I am
simply comparing the values of the pointers themselves, i.e. I am
comparing the addresses, not the contents of the memory that is pointed
to.
Suppose that pointer 0xdeadbeef is some valid "bucket of chicken" pointer in
your list. You assign that pointer to some struct in memory and say,
"Here's your bucket of chicken."
Later on, the pointer 0xdeadbeef gets freed. Now, we have this pointer,
0xdeadbeef and we want to know if it is valid. If we examine our "bucket of
chicken" pointer and say:
pointer 0 in the list is 0xc0ffc0ff. Is pointer 0xc0ffc0ff equal to pointer
0xdeadbeef?

The simple act of examining the contents of the pointer that is storing
0xdeadbeef invokes undefined behavior. Your computer could dump core, or
Scott Nudds could come flying out of your left nostril. Really, it's
practically in the standard. At least comp.std.c made a similar remark
concerning demons some time ago.
Jul 14 '06 #13

P: n/a

Dann Corbit wrote:
"avasilev" <al********@gmail.comwrote in message
news:11**********************@m79g2000cwm.googlegr oups.com...

avasilev wrote:
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.
Ok I will clarify this a bit, sice some people did not get it properly.
I have a list of instance pointers. Every allocated instance is added
to this list and every freed instance is immediately removed from
there. The problem is that copies of these pointers need to be passed
around, and it may happen that when such a copy has to be used, the
instance it points to may be already gone. So a way to validate the
pointer is needed - and this pointer comparison approach was chosen -
not by me, I am kindof revising the thing. So my question was to
confirm how reliable is the current verification mechanism. My opinion
is that it is not, since pointer values for different instances (in
time) may conicide.

If you know for sure that:
1. The pointers in your list are valid pointers (all the bad ones, having
been removed)
2. The pointers in your list point to the appropriate data type

You still have a problem.

Suppose that pointer 0xdeadbeef is some valid "bucket of chicken" pointer in
your list. You assign that pointer to some struct in memory and say,
"Here's your bucket of chicken."
Later on, the pointer 0xdeadbeef gets freed. Now, we have this pointer,
0xdeadbeef and we want to know if it is valid. If we examine our "bucket of
chicken" pointer and say:
pointer 0 in the list is 0xc0ffc0ff. Is pointer 0xc0ffc0ff equal to pointer
0xdeadbeef?

The simple act of examining the contents of the pointer that is storing
0xdeadbeef invokes undefined behavior. Your computer could dump core, or
Scott Nudds could come flying out of your left nostril. Really, it's
practically in the standard. At least comp.std.c made a similar remark
concerning demons some time ago.
No no, Im no examining the moemory that hte pointer points to, I am
simply comparing the values of the pointers themselves, i.e. I am
comparing the addresses, not the contents of the memory that is pointed
to.

Jul 14 '06 #14

P: n/a
"avasilev" <al********@gmail.comwrites:
Dann Corbit wrote:
[...]
>The simple act of examining the contents of the pointer that is storing
0xdeadbeef invokes undefined behavior. Your computer could dump core, or
Scott Nudds could come flying out of your left nostril. Really, it's
practically in the standard. At least comp.std.c made a similar remark
concerning demons some time ago.

No no, Im no examining the moemory that hte pointer points to, I am
simply comparing the values of the pointers themselves, i.e. I am
comparing the addresses, not the contents of the memory that is pointed
to.
Understood, but just examining the pointer value itself, without
dereferencing it, invokes undefined behavior.

Concretely:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *ptr;
ptr = malloc(42);
printf("ptr = %p\n", ptr);
free(ptr);
printf("ptr = %p\n", ptr);
return 0;
}

The second printf call invokes UB (assuming the malloc() succeeded).

In real life, this is unlikely to cause any problems, but strictly
speaking a pointer to an object becomes indeterminate when the object
reaches the end of its lifetime.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 14 '06 #15

P: n/a
avasilev wrote:
[...]
Ok I will clarify this a bit, sice some people did not get it properly.
I have a list of instance pointers. Every allocated instance is added
to this list and every freed instance is immediately removed from
there. The problem is that copies of these pointers need to be passed
around, and it may happen that when such a copy has to be used, the
instance it points to may be already gone. So a way to validate the
pointer is needed - and this pointer comparison approach was chosen -
not by me, I am kindof revising the thing. So my question was to
confirm how reliable is the current verification mechanism. My opinion
is that it is not, since pointer values for different instances (in
time) may conicide.
Well, I'm sure that many people will (rightly so) tell you that if
you free memory, that you should make sure that no pointers to it
will ever be used again.

Short of never free()ing any of your instances (a very bad idea),
or making sure to never reference a free()ed instance (a very good
idea), the only semi-bad solution I see would be to keep track of
all previously-allocated-but-now-freed addresses, and have your
allocate routine check if malloc returned one of them. If so,
keep malloc'ing until a non-previously-used address is returned,
and use that one. (And then free all of the "bad" ones, to keep
from having a memory leak.)

Of course, that "solution" just says "eww, yuck!" to me.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Jul 14 '06 #16

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11**********************@m79g2000cwm.googlegr oups.com...
[snip]
No no, Im no examining the moemory that hte pointer points to, I am
simply comparing the values of the pointers themselves, i.e. I am
comparing the addresses, not the contents of the memory that is pointed
to.
If p is an invalid pointer, then even:

p; /* Not much of a statement here. */

invokes undefined behavior.
Jul 14 '06 #17

P: n/a

avasilev wrote:
Dann Corbit wrote:
"avasilev" <al********@gmail.comwrote in message
news:11**********************@m79g2000cwm.googlegr oups.com...
>
avasilev wrote:
>Hi all,
>>
>my question is:
>>
>if i allocate some memory with malloc() and later free it (using
>free()), is there a possibility that a consequent malloc() will
>allocate memort at the same starting address and will return the same
>pointer as the previous malloc(). I would like to have confirmation on
>whether this is practically a concern when pointers are used to
>uniquely identify data structure instances - like in this example:
>>
>int isInstanceValid(myStrict* inst)
>{
> int i;
> for (i=0; i<instCount; ++i)
> if (instances[i] == inst)
> return 1;
>>
> return 0;
>}
>>
>In this example, if an instance is freed, and a pointer to it becomes
>non-valid, and later a new structure is allocated in the list, the
>function will return that the pointer is valid, although it is actually
>not the instance that was originally referred.
>
Ok I will clarify this a bit, sice some people did not get it properly.
I have a list of instance pointers. Every allocated instance is added
to this list and every freed instance is immediately removed from
there. The problem is that copies of these pointers need to be passed
around, and it may happen that when such a copy has to be used, the
instance it points to may be already gone. So a way to validate the
pointer is needed - and this pointer comparison approach was chosen -
not by me, I am kindof revising the thing. So my question was to
confirm how reliable is the current verification mechanism. My opinion
is that it is not, since pointer values for different instances (in
time) may conicide.
If you know for sure that:
1. The pointers in your list are valid pointers (all the bad ones, having
been removed)
2. The pointers in your list point to the appropriate data type

You still have a problem.

Suppose that pointer 0xdeadbeef is some valid "bucket of chicken" pointer in
your list. You assign that pointer to some struct in memory and say,
"Here's your bucket of chicken."
Later on, the pointer 0xdeadbeef gets freed. Now, we have this pointer,
0xdeadbeef and we want to know if it is valid. If we examine our "bucket of
chicken" pointer and say:
pointer 0 in the list is 0xc0ffc0ff. Is pointer 0xc0ffc0ff equal to pointer
0xdeadbeef?

The simple act of examining the contents of the pointer that is storing
0xdeadbeef invokes undefined behavior. Your computer could dump core, or
Scott Nudds could come flying out of your left nostril. Really, it's
practically in the standard. At least comp.std.c made a similar remark
concerning demons some time ago.

No no, Im no examining the moemory that hte pointer points to, I am
simply comparing the values of the pointers themselves, i.e. I am
comparing the addresses, not the contents of the memory that is pointed
to.

Here is another example:

//this is how we add an instance
struct myStruct* newInst()
{
myStruct* inst = (myStruct*) malloc(sizeof myStruct);

//add the new instance to the linked list of instances
inst->next = instList;
instList = inst;
return inst;
}

//this is how we free an instance and remove it form the list
int delInst(myStruct* inst)
{
myStruct* cur = instList;
while (cur)
{
if (inst == cur)
{
/ /some code to remove from linked list goes here
free(cur);
return 1;
}
cur = cur->next;
}
return 0;
}

int isInstValid(myStruct* inst)
{
myStruct* cur = instList;
while (cur)
{
if (inst == cur) //here we compare the pointers themselves, not
touching hte memory they point to
return 1;
cur = cur->next;
}

return 0;
}
//and this is how we use this stuff

something = newInst();

....... a lot of code aexecuted here and possibly instance was deleted
from the list and freed

if (isInstValid(something))
doSomeStuffWithInstance(something);
else
//probably immediately set something to NULL
The problem is that even if 'if (isInstValid(something))' returns
true, the instance that 'something' points to may be not the original
one, but one that was allocated later, after the original one was
freed, both having hte same address by coincidence.

Jul 14 '06 #18

P: n/a
"Kenneth Brody" <ke******@spamcop.netwrote in message
news:44***************@spamcop.net...
avasilev wrote:
[...]
>Ok I will clarify this a bit, sice some people did not get it properly.
I have a list of instance pointers. Every allocated instance is added
to this list and every freed instance is immediately removed from
there. The problem is that copies of these pointers need to be passed
around, and it may happen that when such a copy has to be used, the
instance it points to may be already gone. So a way to validate the
pointer is needed - and this pointer comparison approach was chosen -
not by me, I am kindof revising the thing. So my question was to
confirm how reliable is the current verification mechanism. My opinion
is that it is not, since pointer values for different instances (in
time) may conicide.

Well, I'm sure that many people will (rightly so) tell you that if
you free memory, that you should make sure that no pointers to it
will ever be used again.

Short of never free()ing any of your instances (a very bad idea),
or making sure to never reference a free()ed instance (a very good
idea), the only semi-bad solution I see would be to keep track of
all previously-allocated-but-now-freed addresses, and have your
allocate routine check if malloc returned one of them. If so,
keep malloc'ing until a non-previously-used address is returned,
and use that one. (And then free all of the "bad" ones, to keep
from having a memory leak.)

Of course, that "solution" just says "eww, yuck!" to me.
It sounds a little to me like the data structure is upside down, or
disconnected.

Can the list of pointers to objects manage the links to external references?

I would like to know more about the problem. Why do the external objects
have pointers to a list of things that may disappear? What do they do with
the pointers? Why are the external objects not members of the structs in
the pointer list (e.g as a linked list or something).

I think that the tracking homework is strangely designed and I think that
good answers to the questions will depend on why these foreign objects have
addresses of potentially disappearing objects. Do multiple external items
point to the same list object address? What do they use this address for?

How can an external object from the list tell the difference between a
pointer to an object originally allocated to them verses a pointer to a
similar object (allocated with the same address) but allocated for a
different set of external objects?
--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>


Jul 14 '06 #19

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11*********************@b28g2000cwb.googlegro ups.com...
Here is another example:

//this is how we add an instance
struct myStruct* newInst()
{
myStruct* inst = (myStruct*) malloc(sizeof myStruct);

//add the new instance to the linked list of instances
inst->next = instList;
instList = inst;
return inst;
}

//this is how we free an instance and remove it form the list
int delInst(myStruct* inst)
{
myStruct* cur = instList;
while (cur)
{
if (inst == cur)
{
/ /some code to remove from linked list goes here
free(cur);
return 1;
}
cur = cur->next;
}
return 0;
}

int isInstValid(myStruct* inst)
{
myStruct* cur = instList;
while (cur)
{
if (inst == cur) //here we compare the pointers themselves, not
This comparison invokes undefined behavior. It may not make your computer
dump core, but it could -- especially if you change compilers or move to
another platform.
touching hte memory they point to
return 1;
cur = cur->next;
}

return 0;
}
//and this is how we use this stuff

something = newInst();

...... a lot of code aexecuted here and possibly instance was deleted
from the list and freed

if (isInstValid(something))
doSomeStuffWithInstance(something);
else
//probably immediately set something to NULL
The problem is that even if 'if (isInstValid(something))' returns
true, the instance that 'something' points to may be not the original
one, but one that was allocated later, after the original one was
freed, both having hte same address by coincidence.
Yes, this is a real possibility.

What about a doubly linked list? Add a doubly linked list to the main data
structure, and use that list exclusively for creating objects that refer
back to the parent. The child objects can find their parents, and the
parent objects can find their children.
Jul 14 '06 #20

P: n/a
avasilev wrote:
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.
Aside from everything else that's already been said: don't do this.

There is no way to detect whether a pointer is valid (in any sense of the
word) in portable C, and in most cases it's not feasible to do it in
unportable C either.

If you concerned about not deallocating things before their time is up, use
a garbage collector, like http://www.hpl.hp.com/personal/Hans_Boehm/gc/.

If you're concerned about sloppy programmers (possibly including yourself as
a culprit), then audit your code more closely, using tools like valgrind
(http://valgrind.org/) and Electric Fence
(http://perens.com/FreeSoftware/ElectricFence/).

If you want a unique identifier for an object, come up with one yourself,
and don't make it depend (exclusively) on its address. This is what the
concept of a handle is all about, although handles are subject to mistakes
like these too. You may be able to devise a handle allocation scheme that
will maximimze the time before reuse and hence increase the chance of
detecting an invalid handle.

The best even most external tools can do is increase the likelihood of
detecting an allocation bug. They cannot convince you there aren't any.

S.
Jul 14 '06 #21

P: n/a

Dann Corbit wrote:
"Kenneth Brody" <ke******@spamcop.netwrote in message
news:44***************@spamcop.net...
avasilev wrote:
[...]
Ok I will clarify this a bit, sice some people did not get it properly.
I have a list of instance pointers. Every allocated instance is added
to this list and every freed instance is immediately removed from
there. The problem is that copies of these pointers need to be passed
around, and it may happen that when such a copy has to be used, the
instance it points to may be already gone. So a way to validate the
pointer is needed - and this pointer comparison approach was chosen -
not by me, I am kindof revising the thing. So my question was to
confirm how reliable is the current verification mechanism. My opinion
is that it is not, since pointer values for different instances (in
time) may conicide.
Well, I'm sure that many people will (rightly so) tell you that if
you free memory, that you should make sure that no pointers to it
will ever be used again.

Short of never free()ing any of your instances (a very bad idea),
or making sure to never reference a free()ed instance (a very good
idea), the only semi-bad solution I see would be to keep track of
all previously-allocated-but-now-freed addresses, and have your
allocate routine check if malloc returned one of them. If so,
keep malloc'ing until a non-previously-used address is returned,
and use that one. (And then free all of the "bad" ones, to keep
from having a memory leak.)

Of course, that "solution" just says "eww, yuck!" to me.

It sounds a little to me like the data structure is upside down, or
disconnected.

Can the list of pointers to objects manage the links to external references?

I would like to know more about the problem. Why do the external objects
have pointers to a list of things that may disappear? What do they do with
the pointers? Why are the external objects not members of the structs in
the pointer list (e.g as a linked list or something).

I think that the tracking homework is strangely designed and I think that
good answers to the questions will depend on why these foreign objects have
addresses of potentially disappearing objects. Do multiple external items
point to the same list object address? What do they use this address for?

How can an external object from the list tell the difference between a
pointer to an object originally allocated to them verses a pointer to a
similar object (allocated with the same address) but allocated for a
different set of external objects?
Er, what do you understand by external objects? If you mean the global
variable instList, this is the pointer to the whole list. When an
instance is to be freed, it is first removed from the list, and then
free()-d (see code). So all pointers in the list are always valid.
Unfortunately I cannot keep track of all copies of these pointers that
fly around in the application. Thats why the whole problem arises.

Jul 14 '06 #22

P: n/a

Keith Thompson wrote:
"avasilev" <al********@gmail.comwrites:
Dann Corbit wrote:
[...]
The simple act of examining the contents of the pointer that is storing
0xdeadbeef invokes undefined behavior. Your computer could dump core, or
Scott Nudds could come flying out of your left nostril. Really, it's
practically in the standard. At least comp.std.c made a similar remark
concerning demons some time ago.
No no, Im no examining the moemory that hte pointer points to, I am
simply comparing the values of the pointers themselves, i.e. I am
comparing the addresses, not the contents of the memory that is pointed
to.

Understood, but just examining the pointer value itself, without
dereferencing it, invokes undefined behavior.

Concretely:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *ptr;
ptr = malloc(42);
printf("ptr = %p\n", ptr);
free(ptr);
printf("ptr = %p\n", ptr);
return 0;
}

The second printf call invokes UB (assuming the malloc() succeeded).

In real life, this is unlikely to cause any problems, but strictly
speaking a pointer to an object becomes indeterminate when the object
reaches the end of its lifetime.
Hmm, ok this means that the compiler may try to do something "hidden"
with this pointer, i.e. try to dereference it somehow? At the assembly
level a pointer is just a register value which can be manupulated just
as any other value, as long as no attempts are made to dereference it.
So do you mean that the C standard states that accessing the value of a
pointer to a freed object causes undefined behaviour?

Jul 14 '06 #23

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11**********************@h48g2000cwc.googlegr oups.com...
[snip]
Unfortunately I cannot keep track of all copies of these pointers that
fly around in the application. Thats why the whole problem arises.
That is the gist of the problem, I think.

You need to devise a way so that you *can* track all of the copies of the
pointers that are flying around. Without that, you have a dangerous design.

IMO-YMMV.
Jul 14 '06 #24

P: n/a

Dann Corbit wrote:
"avasilev" <al********@gmail.comwrote in message
news:11**********************@h48g2000cwc.googlegr oups.com...
[snip]
Unfortunately I cannot keep track of all copies of these pointers that
fly around in the application. Thats why the whole problem arises.

That is the gist of the problem, I think.

You need to devise a way so that you *can* track all of the copies of the
pointers that are flying around. Without that, you have a dangerous design.

IMO-YMMV.
The design is of an already written application (not by me) and I have
to live with it. I just want to eveluate what i can expect from this
approach. If I had to implement it, I would use unique ID-s.

Jul 14 '06 #25

P: n/a

Skarmander wrote:
avasilev wrote:
Hi all,

my question is:

if i allocate some memory with malloc() and later free it (using
free()), is there a possibility that a consequent malloc() will
allocate memort at the same starting address and will return the same
pointer as the previous malloc(). I would like to have confirmation on
whether this is practically a concern when pointers are used to
uniquely identify data structure instances - like in this example:

int isInstanceValid(myStrict* inst)
{
int i;
for (i=0; i<instCount; ++i)
if (instances[i] == inst)
return 1;

return 0;
}

In this example, if an instance is freed, and a pointer to it becomes
non-valid, and later a new structure is allocated in the list, the
function will return that the pointer is valid, although it is actually
not the instance that was originally referred.
Aside from everything else that's already been said: don't do this.

There is no way to detect whether a pointer is valid (in any sense of the
word) in portable C, and in most cases it's not feasible to do it in
unportable C either.

If you concerned about not deallocating things before their time is up, use
a garbage collector, like http://www.hpl.hp.com/personal/Hans_Boehm/gc/.

If you're concerned about sloppy programmers (possibly including yourself as
a culprit), then audit your code more closely, using tools like valgrind
(http://valgrind.org/) and Electric Fence
(http://perens.com/FreeSoftware/ElectricFence/).

If you want a unique identifier for an object, come up with one yourself,
and don't make it depend (exclusively) on its address. This is what the
concept of a handle is all about, although handles are subject to mistakes
like these too. You may be able to devise a handle allocation scheme that
will maximimze the time before reuse and hence increase the chance of
detecting an invalid handle.

The best even most external tools can do is increase the likelihood of
detecting an allocation bug. They cannot convince you there aren't any.

S.
Yes, I would use some sort of UID-s if I had to design it, but it is
already done, so I need to evaluate the current situation.

Jul 14 '06 #26

P: n/a


avasilev wrote On 07/14/06 16:56,:
[...]

//this is how we free an instance and remove it form the list
int delInst(myStruct* inst)
{
myStruct* cur = instList;
while (cur)
{
if (inst == cur)
{
/ /some code to remove from linked list goes here
free(cur);
return 1;
}
cur = cur->next;
}
return 0;
}
The only 100% reliable way to make this scheme work
is to remove the call to free() above. Others have pointed
out that any use of a free'd pointer, even a mere comparison,
produces undefined behavior -- and while this is correct, it
is mostly a "theoretical" concern. However, a "practical"
concern is that malloc() can and usually does re-use free'd
memory; malloc() can return the same non-NULL value N times.
(Because of the "theoretical" U.B., there is no safe way for
a program to detect this reliably, but as a "practical" matter
it does happen, and quite commonly.)

So: The only way to be sure malloc() never returns the
same value twice is never to free() anything. Of course,
this may have unwelcome consequences ...

--
Er*********@sun.com

Jul 14 '06 #27

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11**********************@m79g2000cwm.googlegr oups.com...
>
Dann Corbit wrote:
>"avasilev" <al********@gmail.comwrote in message
news:11**********************@h48g2000cwc.googleg roups.com...
[snip]
Unfortunately I cannot keep track of all copies of these pointers that
fly around in the application. Thats why the whole problem arises.

That is the gist of the problem, I think.

You need to devise a way so that you *can* track all of the copies of the
pointers that are flying around. Without that, you have a dangerous
design.

IMO-YMMV.

The design is of an already written application (not by me) and I have
to live with it. I just want to eveluate what i can expect from this
approach. If I had to implement it, I would use unique ID-s.
Perhaps it can be repaired.

If you can create a data structure that knows about both the object list and
all the objects that refer to it, you can do things like:
tag the non-list objects that use a particular list objects as invalid when
free() is called for that particular list object.

You could implement a reference counting scheme to know if someone is still
using an object so that it should not be freed.
Jul 14 '06 #28

P: n/a

Eric Sosman wrote:
avasilev wrote On 07/14/06 16:56,:
[...]

//this is how we free an instance and remove it form the list
int delInst(myStruct* inst)
{
myStruct* cur = instList;
while (cur)
{
if (inst == cur)
{
/ /some code to remove from linked list goes here
free(cur);
return 1;
}
cur = cur->next;
}
return 0;
}

The only 100% reliable way to make this scheme work
is to remove the call to free() above. Others have pointed
out that any use of a free'd pointer, even a mere comparison,
produces undefined behavior -- and while this is correct, it
is mostly a "theoretical" concern. However, a "practical"
concern is that malloc() can and usually does re-use free'd
memory; malloc() can return the same non-NULL value N times.
(Because of the "theoretical" U.B., there is no safe way for
a program to detect this reliably, but as a "practical" matter
it does happen, and quite commonly.)

So: The only way to be sure malloc() never returns the
same value twice is never to free() anything. Of course,
this may have unwelcome consequences ...

--
Er*********@sun.com

Hm, thats the strange thing here - the code is part of a widely used
open source cross-patform library, which supports a huge diversity of
compilers and platforms. And this code works on all... So, as you say
it seems that the problem with reading a pointer to free-d memory
should be theoretical. But it is really interesting that nobody has
complained so far about this.

Jul 14 '06 #29

P: n/a

Dann Corbit wrote:
"avasilev" <al********@gmail.comwrote in message
news:11**********************@m79g2000cwm.googlegr oups.com...

Dann Corbit wrote:
"avasilev" <al********@gmail.comwrote in message
news:11**********************@h48g2000cwc.googlegr oups.com...
[snip]
Unfortunately I cannot keep track of all copies of these pointers that
fly around in the application. Thats why the whole problem arises.

That is the gist of the problem, I think.

You need to devise a way so that you *can* track all of the copies of the
pointers that are flying around. Without that, you have a dangerous
design.

IMO-YMMV.
The design is of an already written application (not by me) and I have
to live with it. I just want to eveluate what i can expect from this
approach. If I had to implement it, I would use unique ID-s.

Perhaps it can be repaired.

If you can create a data structure that knows about both the object list and
all the objects that refer to it, you can do things like:
tag the non-list objects that use a particular list objects as invalid when
free() is called for that particular list object.

You could implement a reference counting scheme to know if someone is still
using an object so that it should not be freed.

Yes, your idea is good. However this mechanism is deeply in the core of
the library, and changing it wil lrequire a lot of efforts. Strangely
this has been working on numerous platforms and compilers - the code is
part of an opensource crosspatform library.

Jul 14 '06 #30

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11*********************@b28g2000cwb.googlegro ups.com...
[snip]
Hm, thats the strange thing here - the code is part of a widely used
open source cross-patform library, which supports a huge diversity of
compilers and platforms. And this code works on all... So, as you say
it seems that the problem with reading a pointer to free-d memory
should be theoretical. But it is really interesting that nobody has
complained so far about this.
What open source tool kit did the code come from?
Jul 14 '06 #31

P: n/a

Dann Corbit wrote:
"avasilev" <al********@gmail.comwrote in message
news:11*********************@b28g2000cwb.googlegro ups.com...
[snip]
Hm, thats the strange thing here - the code is part of a widely used
open source cross-patform library, which supports a huge diversity of
compilers and platforms. And this code works on all... So, as you say
it seems that the problem with reading a pointer to free-d memory
should be theoretical. But it is really interesting that nobody has
complained so far about this.
What open source tool kit did the code come from?
iaxclient, in libiax2 - iax.c
This is the way sessions are handled.

Jul 14 '06 #32

P: n/a
"avasilev" <al********@gmail.comwrites:
Keith Thompson wrote:
>"avasilev" <al********@gmail.comwrites:
[...]
No no, Im no examining the moemory that hte pointer points to, I am
simply comparing the values of the pointers themselves, i.e. I am
comparing the addresses, not the contents of the memory that is pointed
to.

Understood, but just examining the pointer value itself, without
dereferencing it, invokes undefined behavior.

Concretely:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *ptr;
ptr = malloc(42);
printf("ptr = %p\n", ptr);
free(ptr);
printf("ptr = %p\n", ptr);
return 0;
}

The second printf call invokes UB (assuming the malloc() succeeded).

In real life, this is unlikely to cause any problems, but strictly
speaking a pointer to an object becomes indeterminate when the object
reaches the end of its lifetime.

Hmm, ok this means that the compiler may try to do something "hidden"
with this pointer, i.e. try to dereference it somehow? At the assembly
level a pointer is just a register value which can be manupulated just
as any other value, as long as no attempts are made to dereference it.
So do you mean that the C standard states that accessing the value of a
pointer to a freed object causes undefined behaviour?
Yes, exactly.

For example, suppose the CPU has special address registers and the
ability to check whether a given address is either valid or null
(i.e., a null pointer is valid, a pointer to an existing object is
valid, and any other pointer is invalid). It makes sense to do this
check as early as possible, i.e., when the address is loaded into an
address register. The standard is designed to make such an
implementation legal.

When you pass a pointer to free(), you're promising that you're
finished with it. By examining the value of the pointer later on,
you're breaking that promise, and the implementation is free to strike
down upon thee with great vengeance and furious anger -- or, if it's
in a good mood, merely to crash your program.

(Note that you can examine the *representation* of any object by
treating it as an array of unsigned char, and it's been persuasively
argued that free() cannot change the representation of a pointer --
but I wouldn't necessarily suggest taking advantage of that.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 14 '06 #33

P: n/a
>shouldnt be a problem, because if you're really keeping track of valid
>pointers with that table, anytime you do a free() on a pointer you MUST
be removing that entry from the table.

Yes, but later I can allocate a new pointer and add it to the table, it
could happen to have the same value. Then a previously non-vaid pointer
becomes valid now.
If you keep freeing and reallocating chunks of memory, eventually
malloc() *MUST* either fail (return NULL) or return the same pointer
as it did before. Pointers have only a finite number of bits. If
pointers have 32 bits, you're guaranteed to have a repeat before
(2**32)+1 calls to malloc(), and possibly a lot sooner than that
if parts of the address space aren't used for dynamically allocated
memory.

Gordon L. Burditt
Jul 15 '06 #34

P: n/a
>Hmm, ok this means that the compiler may try to do something "hidden"
>with this pointer, i.e. try to dereference it somehow?
On a rather obscure processor which I'm sure nobody ever heard of,
the Intel Pentium, in protected mode, if you load an invalid segment
(hint: part of a pointer in large memory model) into a segment
register, you may get a trap which likely maps to some kind of
signal or program abort.

On the other hand, it's not that unreasonable for a compiler to
generate code to load a pointer it's about to use (maybe) into a
segment:offset register pair once early since reloading it repeatedly
is expensive.

The processor might also leave a pointer around in a segment register
from when it was valid (before free() got called), then try to save
and restore the segment registers with push/pop instructions, so
you can get traps at odd times when the pointer with the invalid
value isn't apparently being used.
>At the assembly
level a pointer is just a register value which can be manupulated just
as any other value, as long as no attempts are made to dereference it.
At the assembly level, you cannot put arbitrary bit patterns in the
segment registers without risking traps depending on the contents
of the corresponding segment table entry (which may well be changed
as the result of a malloc() or free() call). Get a manual on the
Intel Pentium and look it up. Oh, yes, the all-bits-zero segment
(a logical thing to use for NULL) is treated specially: it doesn't
cause a trap to load it in a segment register but it does if you
dereference it. It looks like Intel designed this with C (along
with other languages with null pointers) in mind.
>So do you mean that the C standard states that accessing the value of a
pointer to a freed object causes undefined behaviour?
Yes. Guess what? The undefined behavior that happens occurs at
the assembly-language level in this case.

Gordon L. Burditt
Jul 15 '06 #35

P: n/a

avasilev wrote:
>
The design is of an already written application (not by me) and I have
to live with it. I just want to eveluate what i can expect from this
approach. If I had to implement it, I would use unique ID-s.
This might be a Herculean task for an already-written application, but
if I were writing one from scratch, rather than this unique ID
nonsense, what I like to do is write custom free functions for various
structures, for instance i have widgets and any given widget might have
pointers pointing to it from thingies or from other widgets. I might
write something like

void free_widget( struct widget *w )
{
struct widget *w2;
struct thingy *t;

for ( w2 = first_widget; w2; w2 = w2->next )
if ( w2->widgetpointer == w )
w2->widgetpointer = NULL;

for (t = first_thingy; t; t = t->next )
if ( t->widgetpointer == v )
t->widgetpointer = NULL;

free( w );
return;
}

Of course this is a very simple example since in practice it'd be more
likely that (for instance) each thingy would contain an entire linked
list of pointers to various widgets, etc. But you get the idea.

Jul 15 '06 #36

P: n/a

Gordon Burditt wrote:
Hmm, ok this means that the compiler may try to do something "hidden"
with this pointer, i.e. try to dereference it somehow?

On a rather obscure processor which I'm sure nobody ever heard of,
the Intel Pentium, in protected mode, if you load an invalid segment
(hint: part of a pointer in large memory model) into a segment
register, you may get a trap which likely maps to some kind of
signal or program abort.

On the other hand, it's not that unreasonable for a compiler to
generate code to load a pointer it's about to use (maybe) into a
segment:offset register pair once early since reloading it repeatedly
is expensive.

The processor might also leave a pointer around in a segment register
from when it was valid (before free() got called), then try to save
and restore the segment registers with push/pop instructions, so
you can get traps at odd times when the pointer with the invalid
value isn't apparently being used.
At the assembly
level a pointer is just a register value which can be manupulated just
as any other value, as long as no attempts are made to dereference it.

At the assembly level, you cannot put arbitrary bit patterns in the
segment registers without risking traps depending on the contents
of the corresponding segment table entry (which may well be changed
as the result of a malloc() or free() call). Get a manual on the
Intel Pentium and look it up. Oh, yes, the all-bits-zero segment
(a logical thing to use for NULL) is treated specially: it doesn't
cause a trap to load it in a segment register but it does if you
dereference it. It looks like Intel designed this with C (along
with other languages with null pointers) in mind.
So do you mean that the C standard states that accessing the value of a
pointer to a freed object causes undefined behaviour?

Yes. Guess what? The undefined behavior that happens occurs at
the assembly-language level in this case.

And lest anyone think this is purely theoretical problem...

I know of a 16-bit compiler (not C) that passed the first few
parameters (of appropriate type) in registers, and the first two far
pointers were passed in es:di and ds:si (assuming those were
available). And yes, just passing a free'd pointer to a subroutine
would cause an abend.

OTOH, I don't know of any C compilers that did that. MS's 16 bit
register calling convention could pass near pointers in registers but
always passed far pointers on the stack.

Jul 15 '06 #37

P: n/a

Snis Pilbor wrote:
avasilev wrote:

The design is of an already written application (not by me) and I have
to live with it. I just want to eveluate what i can expect from this
approach. If I had to implement it, I would use unique ID-s.

This might be a Herculean task for an already-written application, but
if I were writing one from scratch, rather than this unique ID
nonsense, what I like to do is write custom free functions for various
structures, for instance i have widgets and any given widget might have
pointers pointing to it from thingies or from other widgets. I might
write something like

void free_widget( struct widget *w )
{
struct widget *w2;
struct thingy *t;

for ( w2 = first_widget; w2; w2 = w2->next )
if ( w2->widgetpointer == w )
w2->widgetpointer = NULL;

for (t = first_thingy; t; t = t->next )
if ( t->widgetpointer == v )
t->widgetpointer = NULL;

free( w );
return;
}

Of course this is a very simple example since in practice it'd be more
likely that (for instance) each thingy would contain an entire linked
list of pointers to various widgets, etc. But you get the idea.
I don't think this will help him. If he has multiple modules with a
pointer to an object and any one of them may free it at any time, with
a custom or non custom free, there is a design flaw that needs to be
fixed.

Jul 15 '06 #38

P: n/a
avasilev wrote:
Ancient_Hacker wrote:
>shouldnt be a problem, because if you're really keeping track of valid
pointers with that table, anytime you do a free() on a pointer you MUST
be removing that entry from the table.

Yes, but later I can allocate a new pointer and add it to the table, it
could happen to have the same value. Then a previously non-vaid pointer
becomes valid now.
And that's one of the reasons a function like you're trying to
implement is a rather futile approach.

Jul 15 '06 #39

P: n/a

Gordon Burditt wrote:
Hmm, ok this means that the compiler may try to do something "hidden"
with this pointer, i.e. try to dereference it somehow?

On a rather obscure processor which I'm sure nobody ever heard of,
the Intel Pentium, in protected mode, if you load an invalid segment
(hint: part of a pointer in large memory model) into a segment
register, you may get a trap which likely maps to some kind of
signal or program abort.

On the other hand, it's not that unreasonable for a compiler to
generate code to load a pointer it's about to use (maybe) into a
segment:offset register pair once early since reloading it repeatedly
is expensive.

The processor might also leave a pointer around in a segment register
from when it was valid (before free() got called), then try to save
and restore the segment registers with push/pop instructions, so
you can get traps at odd times when the pointer with the invalid
value isn't apparently being used.
At the assembly
level a pointer is just a register value which can be manupulated just
as any other value, as long as no attempts are made to dereference it.

At the assembly level, you cannot put arbitrary bit patterns in the
segment registers without risking traps depending on the contents
of the corresponding segment table entry (which may well be changed
as the result of a malloc() or free() call). Get a manual on the
Intel Pentium and look it up. Oh, yes, the all-bits-zero segment
(a logical thing to use for NULL) is treated specially: it doesn't
cause a trap to load it in a segment register but it does if you
dereference it. It looks like Intel designed this with C (along
with other languages with null pointers) in mind.
So do you mean that the C standard states that accessing the value of a
pointer to a freed object causes undefined behaviour?

Yes. Guess what? The undefined behavior that happens occurs at
the assembly-language level in this case.

Gordon L. Burditt

Ok, I got your point - segment registers. The thing is that this
approach that I am discussing ia actually used in a opensource cross
platform library. It runs on *nix, windows and macos. Nobody had
problems with this, ar at least nobody fixed this so far. My point is -
these OS-es do not use segmentation for the memory model of user-mode
processes. So you are right in theory, but in practice this does not
happen. Dont get me wrong, I dont defent this approach, I'm very far
from it - if I had to design it I would use handles. But it is already
done.

Jul 15 '06 #40

P: n/a

sw***********@gmail.com wrote:
Snis Pilbor wrote:
avasilev wrote:
>
The design is of an already written application (not by me) and I have
to live with it. I just want to eveluate what i can expect from this
approach. If I had to implement it, I would use unique ID-s.
This might be a Herculean task for an already-written application, but
if I were writing one from scratch, rather than this unique ID
nonsense, what I like to do is write custom free functions for various
structures, for instance i have widgets and any given widget might have
pointers pointing to it from thingies or from other widgets. I might
write something like

void free_widget( struct widget *w )
{
struct widget *w2;
struct thingy *t;

for ( w2 = first_widget; w2; w2 = w2->next )
if ( w2->widgetpointer == w )
w2->widgetpointer = NULL;

for (t = first_thingy; t; t = t->next )
if ( t->widgetpointer == v )
t->widgetpointer = NULL;

free( w );
return;
}

Of course this is a very simple example since in practice it'd be more
likely that (for instance) each thingy would contain an entire linked
list of pointers to various widgets, etc. But you get the idea.

I don't think this will help him. If he has multiple modules with a
pointer to an object and any one of them may free it at any time, with
a custom or non custom free, there is a design flaw that needs to be
fixed.
Yep, practically using a custom free function which checks and NULL-s
all possible references is not feasible. If nothing else, it is
error-prone. Imagine I add some other place where an instance is
referenced - I have to change the free function every time.

Jul 15 '06 #41

P: n/a
Background: the issue involves using free()d pointers, as in the
following code fragment:

void *p1, *p2;
int i;
void *table[MAX];
...
p1 = malloc(N);
p2 = malloc(N);
table[i] = p1;
free(p);
if (table[i] == p2) ... do something ...

In article <11**********************@m79g2000cwm.googlegroups .com>
avasilev <al********@gmail.comwrote:
>No no, Im no examining the moemory that hte pointer points to, I am
simply comparing the values of the pointers themselves, i.e. I am
comparing the addresses, not the contents of the memory that is pointed
to.
This may not help (although it happens to work on most machines today).
See <http://web.torek.net/c/numbers2.html>.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 16 '06 #42

P: n/a
(More on using free()d memory, and/or malloc() later returning a pointer
value that was at one point free()d.)

In article <11**********************@h48g2000cwc.googlegroups .com>
avasilev <al********@gmail.comwrote:
>[There is a] global
variable instList, this is the pointer to the whole list. When an
instance is to be freed, it is first removed from the list, and then
free()-d (see code). So all pointers in the list are always valid.
Unfortunately I cannot keep track of all copies of these pointers that
fly around in the application. Thats why the whole problem arises.
Let me boil this down to some sample code:

/* xalloc - just like malloc, but panics (aborts) if out of memory */
extern void *xalloc(size_t);

struct obj {
struct obj *next;
... data ...
};
static struct obj *head; /* "global" list head */

/* create a new object, putting it in the list */
struct obj *newobj(void) {
struct obj *new = xalloc(sizeof *new);
new->next = head;
head = new;
...
return new;
}

/* delete an object, which must be in the list */
void deleteobj(struct obj *obj) {
struct obj *p, **pp;

for (pp = &head; (p = *pp) != NULL; pp = &p->next)
if (p == obj)
break;
if (p == NULL)
panic("asked to delete object not in list");

/* at this point, p==obj and it is in the list */
*pp = p->next;
free(p);
}

/* return true if the object is in the list */
int testobj(struct obj *obj) {
struct obj *p;

for (p = head; p != NULL; p = p->next)
if (p == obj)
return 1;
return 0;
}

Now you can call testobj() with a valid pointer, to see if it is
in the global list:

struct obj *p1, *p2;

p1 = newobj();
p2 = newobj();

if (testobj(p1)) ...
if (testobj(p2)) ...

These are all OK (albeit useless; obviously p1 and p2 *are* in
the list at this point).

Here is where things go wrong:

void f2(void) {
struct obj *p1 = newobj();

use(p1);
if (testobj(p1)) ...
...
}

where use() looks like this:

void use(struct obj *p) {
deleteobj(p);
}

Here, the problem is that use() got a copy of the value in p1, and
asked deleteobj() to delete the object. But its caller (f2()) then
continues to use the object.

This is not something that can be detected, in general. One might
as well ask f2() to detect code like this:

void use(struct obj *p) {
memcpy(p, 0xff, 10000); /* smash a bunch of memory, whee! */
}

The problem is not in f2(); the problem is in use(). It cannot be
solved in f2(); it must be solved in use(). The use() function
lights the fuse on a time-bomb; there is no predicting just when
it will go off.

This does not mean that debug routines -- code that gives you a
chance to set the bomb off faster -- are *useless*, just that they
can never be made perfect. The bomb may be trickier than the
defusing code.

If you could find a machine that actually used segment registers
to catch illegal use of free()d pointers, you would not even need
the debug routine. Instead of a delayed-fuse time-bomb, the original
use() -- which incorrectly deletes the object while it is still in
use) -- would set a *non*-delayed fuse that would trigger immediately
upon the return to f2(), when f2() attempts to do any other operation
on p1 (except of course something like "p1 = NULL").

Alas, nobody builds machines designed for debugging anymore.

Now, if you *want* to be able to "pseudo-delete" objects, and
have them only go away when everyone is *really* done with them,
you need a garbage collector, or something that is sufficiently
similar. In this case, you might change "obj" to add a reference
count to it, and have gainref() and deleteref() calls, with the
object going away when its last reference goes away:

struct obj {
int refcnt;
... data ...
};
/* create a new object */
struct obj *newobj(void) {
struct obj *new = xalloc(sizeof *new);
new->refcnt = 1;
...
return new;
}

/* gain an extra reference to an object */
void gainref(struct obj *p) {
p->refcnt++;
}

/* lose a reference to an object */
void deleteref(struct obj *p) {
if (p->refcnt <= 0)
panic("invalid refcnt in deleteref");
if (--p->refcnt == 0)
free(p);
}

Now a function can just add a reference at any time, and delete
one whenever it is done. When the reference count goes to zero,
the object goes away; but not until then.

Of course, a reference counting system only works if you do not
have loops in the data structures (or if those data structures do
not "count themselves", as it were, but this last is terribly
tricky). In this case, you might be better served by a language
that includes built-in garbage-collection.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 16 '06 #43

P: n/a
av
On 16 Jul 2006 08:08:54 GMT, Chris Torek <no****@torek.netwrote:
>(More on using free()d memory, and/or malloc() later returning a pointer
value that was at one point free()d.)

In article <11**********************@h48g2000cwc.googlegroups .com>
avasilev <al********@gmail.comwrote:
>>[There is a] global
variable instList, this is the pointer to the whole list. When an
instance is to be freed, it is first removed from the list, and then
free()-d (see code). So all pointers in the list are always valid.
Unfortunately I cannot keep track of all copies of these pointers that
fly around in the application. Thats why the whole problem arises.

Let me boil this down to some sample code:

/* xalloc - just like malloc, but panics (aborts) if out of memory */
extern void *xalloc(size_t);

struct obj {
struct obj *next;
... data ...
};
static struct obj *head; /* "global" list head */

/* create a new object, putting it in the list */
struct obj *newobj(void) {
struct obj *new = xalloc(sizeof *new);
new->next = head;
head = new;
...
return new;
}

/* delete an object, which must be in the list */
void deleteobj(struct obj *obj) {
struct obj *p, **pp;

for (pp = &head; (p = *pp) != NULL; pp = &p->next)
if (p == obj)
break;
if (p == NULL)
panic("asked to delete object not in list");

/* at this point, p==obj and it is in the list */
*pp = p->next;
free(p);
here p=0;
}

/* return true if the object is in the list */
int testobj(struct obj *obj) {
struct obj *p;

for (p = head; p != NULL; p = p->next)
if (p == obj)
return 1;
return 0;
}

Now you can call testobj() with a valid pointer, to see if it is
in the global list:

struct obj *p1, *p2;

p1 = newobj();
p2 = newobj();

if (testobj(p1)) ...
if (testobj(p2)) ...

These are all OK (albeit useless; obviously p1 and p2 *are* in
the list at this point).

Here is where things go wrong:

void f2(void) {
struct obj *p1 = newobj();

use(p1);
if (testobj(p1)) ...
...
}

where use() looks like this:

void use(struct obj *p) {
deleteobj(p);
}

Here, the problem is that use() got a copy of the value in p1, and
asked deleteobj() to delete the object. But its caller (f2()) then
continues to use the object.
this is not a problem if
void use(struct obj *p) { deleteobj(p); p=0; }
or you change deleteobj like above

otherwhise it is a bug but for me it has not segfault
it have to segfaul only when deference for write
it is possible i like to read memory out my program
>
This is not something that can be detected, in general. One might
as well ask f2() to detect code like this:

void use(struct obj *p) {
memcpy(p, 0xff, 10000); /* smash a bunch of memory, whee! */
}

The problem is not in f2(); the problem is in use(). It cannot be
solved in f2(); it must be solved in use().
no, f2 can see the problem when free p
no, f2 can see the problem when free p
no, f2 can see the problem when free p
no, f2 can see the problem when free p
no, f2 can see the problem when free p
no, f2 can see the problem when free p
no, f2 can see the problem when free p
no, f2 can see the problem when free p
no, f2 can see the problem when free p
The use() function
lights the fuse on a time-bomb; there is no predicting just when
it will go off.
time-bomp is only the code that not self check memory when free it
>This does not mean that debug routines -- code that gives you a
chance to set the bomb off faster -- are *useless*, just that they
can never be made perfect. The bomb may be trickier than the
defusing code.
this is always true but i have 99% of probability to find there is
something wrong and where
>If you could find a machine that actually used segment registers
to catch illegal use of free()d pointers, you would not even need
the debug routine. Instead of a delayed-fuse time-bomb, the original
use() -- which incorrectly deletes the object while it is still in
use) -- would set a *non*-delayed fuse that would trigger immediately
upon the return to f2(), when f2() attempts to do any other operation
on p1 (except of course something like "p1 = NULL").
>Alas, nobody builds machines designed for debugging anymore.

Now, if you *want* to be able to "pseudo-delete" objects, and
have them only go away when everyone is *really* done with them,
you need a garbage collector, or something that is sufficiently
malloc has need a function for check memory when free
garbage collettor is wrong
it is good the c++ way (constructors/destructors)
don't understand the remain are not so smart
then the rest it seems too long and i'm lazy
can you summarize?
>similar. In this case, you might change "obj" to add a reference
count to it, and have gainref() and deleteref() calls, with the
object going away when its last reference goes away:

struct obj {
int refcnt;
... data ...
};
/* create a new object */
struct obj *newobj(void) {
struct obj *new = xalloc(sizeof *new);
new->refcnt = 1;
...
return new;
}

/* gain an extra reference to an object */
void gainref(struct obj *p) {
p->refcnt++;
}

/* lose a reference to an object */
void deleteref(struct obj *p) {
if (p->refcnt <= 0)
panic("invalid refcnt in deleteref");
if (--p->refcnt == 0)
free(p);
}

Now a function can just add a reference at any time, and delete
one whenever it is done. When the reference count goes to zero,
the object goes away; but not until then.

Of course, a reference counting system only works if you do not
have loops in the data structures (or if those data structures do
not "count themselves", as it were, but this last is terribly
tricky). In this case, you might be better served by a language
that includes built-in garbage-collection.
Jul 16 '06 #44

P: n/a
av
On Sun, 16 Jul 2006 11:56:32 +0200, av <av@ala.awrote:
>On 16 Jul 2006 08:08:54 GMT, Chris Torek <no****@torek.netwrote:
>>Let me boil this down to some sample code:

/* xalloc - just like malloc, but panics (aborts) if out of memory */
extern void *xalloc(size_t);

struct obj {
struct obj *next;
... data ...
};
static struct obj *head; /* "global" list head */

/* create a new object, putting it in the list */
struct obj *newobj(void) {
struct obj *new = xalloc(sizeof *new);
new->next = head;
head = new;
...
return new;
}

/* delete an object, which must be in the list */
void deleteobj(struct obj *obj) {
struct obj *p, **pp;

for (pp = &head; (p = *pp) != NULL; pp = &p->next)
if (p == obj)
break;
if (p == NULL)
panic("asked to delete object not in list");

/* at this point, p==obj and it is in the list */
*pp = p->next;
free(p);

here p=0;
wrong it seems here i can not chage p
....
>>Here, the problem is that use() got a copy of the value in p1, and
asked deleteobj() to delete the object. But its caller (f2()) then
continues to use the object.

this is not a problem if
void use(struct obj *p) { deleteobj(p); p=0; }
or you change deleteobj like above
ok i make errors but all you too
>otherwhise it is a bug but for me it has not segfault
it have to segfaul only when deference for write
it is possible i like to read memory out my program
>>
This is not something that can be detected, in general. One might
as well ask f2() to detect code like this:

void use(struct obj *p) {
memcpy(p, 0xff, 10000); /* smash a bunch of memory, whee! */
}

The problem is not in f2(); the problem is in use(). It cannot be
solved in f2(); it must be solved in use().

no, f2 can see the problem when free p
Jul 16 '06 #45

P: n/a

In article <e9********@news4.newsguy.com>, Chris Torek <no****@torek.netwrites:
>
If you could find a machine that actually used segment registers
to catch illegal use of free()d pointers, you would not even need
the debug routine. Instead of a delayed-fuse time-bomb, the original
use() -- which incorrectly deletes the object while it is still in
use) -- would set a *non*-delayed fuse that would trigger immediately
upon the return to f2(), when f2() attempts to do any other operation
on p1 (except of course something like "p1 = NULL").
I can find one. In fact, I have a pretty good idea where it is right
now.

(It does not use "segment registers", as such, to detect this error,
but then the OP's claim that examining a pointer's value "just loads
it into a register" is not universally correct, so segment registers
are only one example of a possible source of trouble.)
Alas, nobody builds machines designed for debugging anymore.
IBM does. Hurrah for capability architectures; it's a pity we don't
have more of them.

--
Michael Wojcik mi************@microfocus.com

Do we have boyfriends? We are interested in delicious food and sweets.
And tiny animals like the cat. -- Naoko Yamano
Jul 16 '06 #46

P: n/a

In article <11**********************@b28g2000cwb.googlegroups .com>, "avasilev" <al********@gmail.comwrites:
>
At the assembly
level a pointer is just a register value which can be manupulated just
as any other value, as long as no attempts are made to dereference it.
The C standard does not require this, and there are conforming
implementations for which it is not true.

Certainly, there are many conforming implementations where it *is*
true, and on those it is generally safe to examine an invalid
pointer value as long as it is not dereferenced; but such code is
not portable beyond those implementations. Whether that is an issue
is up to the authors and users of such code.

--
Michael Wojcik mi************@microfocus.com

An intense imaginative activity accompanied by a psychological and moral
passivity is bound eventually to result in a curbing of the growth to
maturity and in consequent artistic repetitiveness and stultification.
-- D. S. Savage
Jul 16 '06 #47

P: n/a
In article <e9********@news2.newsguy.comI wrote, in part:
>This may not help (although it happens to work on most machines today).
See <http://web.torek.net/c/numbers2.html>.
Oops, wrong URL -- should be http://web.torek.net/torek/c/numbers2.html
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 16 '06 #48

P: n/a
"avasilev" <al********@gmail.comwrote in message
news:11**********************@75g2000cwc.googlegro ups.com...
>
Dann Corbit wrote:
>"avasilev" <al********@gmail.comwrote in message
news:11*********************@b28g2000cwb.googlegr oups.com...
[snip]
Hm, thats the strange thing here - the code is part of a widely used
open source cross-patform library, which supports a huge diversity of
compilers and platforms. And this code works on all... So, as you say
it seems that the problem with reading a pointer to free-d memory
should be theoretical. But it is really interesting that nobody has
complained so far about this.
What open source tool kit did the code come from?

iaxclient, in libiax2 - iax.c
This is the way sessions are handled.
<OT>
libiax2 does not have a very diverse userbase; the majority of people will
be running it on Linux, with a smattering of *BSD, OSX, Win32, and Solaris
users. Those are all relatively forgiving platforms in general, and all
allow you to examine an invalid pointer without trapping in particular. Go
run the code on an AS/400 and you'll see a very different result.
</OT>

Examining an invalid pointer causes UB, period. That means that in some
cases, it will do exactly what you expect (i.e. nothing). However, it
doesn't preclude some implementation from doing something else.

As others have noted, since malloc() is allowed to return duplicate values
if there's been an intervening free(), the code you're working with is
broken even if the behavior _were_ defined. Either you're lucking out that
your code happens to assign those blocks to other data types and thus never
causes a conflict between two instances of the same type, or you're actually
getting false pointer links to the wrong instance of an object and it's
causing subtle bugs you'll never be able to trace.

The only obvious solution to this is to replace bare calls to free() with a
function that walks all of your data structures and NULLs out any pointers
that compare equal before actually free()ing the dead object.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin
--
Posted via a free Usenet account from http://www.teranews.com

Jul 17 '06 #49

This discussion thread is closed

Replies have been disabled for this discussion.