473,785 Members | 3,349 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Does malloc() reuse addresses?

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
48 5853

sw***********@g mail.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->widgetpointe r == w )
w2->widgetpointe r = NULL;

for (t = first_thingy; t; t = t->next )
if ( t->widgetpointe r == v )
t->widgetpointe r = 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
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************ **********@m79g 2000cwm.googleg roups.com>
avasilev <al********@gma il.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
(More on using free()d memory, and/or malloc() later returning a pointer
value that was at one point free()d.)

In article <11************ **********@h48g 2000cwc.googleg roups.com>
avasilev <al********@gma il.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.
Unfortunatel y 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(struc t 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(struc t 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
av
On 16 Jul 2006 08:08:54 GMT, Chris Torek <no****@torek.n etwrote:
>(More on using free()d memory, and/or malloc() later returning a pointer
value that was at one point free()d.)

In article <11************ **********@h48g 2000cwc.googleg roups.com>
avasilev <al********@gma il.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.
Unfortunate ly 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(struc t 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(struc t 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
av
On Sun, 16 Jul 2006 11:56:32 +0200, av <av@ala.awrot e:
>On 16 Jul 2006 08:08:54 GMT, Chris Torek <no****@torek.n etwrote:
>>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(struc t 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

In article <e9********@new s4.newsguy.com> , Chris Torek <no****@torek.n etwrites:
>
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

In article <11************ **********@b28g 2000cwb.googleg roups.com>, "avasilev" <al********@gma il.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
In article <e9********@new s2.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
"avasilev" <al********@gma il.comwrote in message
news:11******** **************@ 75g2000cwc.goog legroups.com...
>
Dann Corbit wrote:
>"avasilev" <al********@gma il.comwrote in message
news:11******* **************@ b28g2000cwb.goo glegroups.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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

33
2726
by: Chris Fogelklou | last post by:
What is wrong with the above? Don't worry, I already know (learned my lesson last week.) It is for the benefit of our resident compiler guru who seems to think you need the cast. I thought it too, up until I started posting here! Thanks, Chris
24
3827
by: David Mathog | last post by:
If this: int i,sum; int *array; for(sum=0, i=0; i<len; i++){ sum += array; } is converted to this (never mind why for the moment):
4
1822
by: Manu | last post by:
Hello, Can we say that the return addresses from the various malloc function calls, in a program, will always be in a predefined order (increasing or decreasing, depeding on how the heap is managed) ? regards Manu
41
3353
by: jacob navia | last post by:
In the C tutorial for lcc-win32, I have a small chapter about a debugging implementation of malloc. Here is the code, and the explanations that go with it. I would appreciate your feedback both about the code and the associated explanations. ---------------------------------------------------------------------
6
3372
by: itsolution | last post by:
Hi folks, Could you shed some light on this issue? my program is running on Freebsd as a daemon. When user sends a request, it forks itself and lets its child process handles the request. And its main role is just to read a big xml file and save each object into its embedded DB(such as gdbm).
0
10319
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10147
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10087
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9947
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8971
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7496
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6737
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
3645
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2877
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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

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