How to know the memory pointed by a ptr is freed?

M

Martin Ambuhl

RCollins said:
Keith Thompson wrote: [...]
If you don't want trivialities nit-picked, I humbly submit that you've
come to the wrong newsgroup. :cool:}
I think you are right ...

More to the point, programming is about nit-picking. If just anyone
could tell the computer, "Hey, solve this problem," programming would
pay less than minimum wage and be done by teenagers under the Republican
"Hire teenagers at below minimum wage to replace adults" job program.
 
F

Flash Gordon

The text is (from C89):
...
Conversions that involve pointers (other than as permitted by the
constraints of $3.3.16.1) shall be specified by means of an explicit
cast; they have implementation-defined aspects: A pointer may be
converted to an integral type. The size of integer required and the
result are implementation-defined. If the space provided is not long
enough, the behavior is undefined.
...

Thank you.
As I noted, it is up to the programmer to make sure the integer type
is wide enough to contain a pointer (and vice versa). And you are
correct, it DOES NOT guarantee that any integer type is wide enough
for the conversion.

So it's worse than I thought in the worst case. You get Undefined
behaviour. :-/

See my response to Keith, where I ask "what is the difference between
a cast from ptr vs. a memcpy() from ptr". It seems to me that if
an implementation is *always* going to check the validity of a
pointer, then it would catch it (invalid pointer) regardless of the
method used.

Kieth has again provided a good explanation. memcpy does not treat ptr
as a pointer, it treats it as an array of unsigned char. Or in other
words, the standard allows you to do it so the implementation has to
allow you to do it. :)

We'll agree on more as I learn more.

Those willing to learn from the answers are worth answering. :)

I've learnt a number of useful things here.
 
C

Chris Torek

I'm sure someone here can point out an implementation with pointers
larger than the largest integer, whether it is modern is another
question.

IBM AS/400, at least for "pointer to function". (Probably also for
"pointer to data" too, but I do not have an AS/400 implementation
handy to check; mainly I remember that function pointers were about
a million times bigger than data pointers. :) OK, maybe 4 or 8
times bigger -- lots more bytes, anyway.)

AS/400s are being sold today, and as far as I know, have at least
C89-conforming compilers. (Remember that the AS/400 is sort of a
"virtual architecture", in the same way the S/370 architecture
was implemented in lots of different kinds of hardware, including
re-microcoded 68000 CPUs.)
 
J

Joe Wright

Flash Gordon wrote:

[ snip ]

I never know where (or whether) to enter these incredible threads
but I do have something to share on the Subject.

Some time ago I determined to add 'size_t size(void *);' to my
otherwise meager bag of tricks.

In the simplist case, a call to malloc() is directed to a wrapper
that actually calls malloc but 'remembers' the size_t argument as
well as the void* return and saves them in a simple linked list.

A call to size(void *p) trips through the linked list looking for
the vallue of p and returns the size of the allocation if found,
else 0. Perfect.

Of course, I wrap free(void *p) as well. We trip through the list
looking for p and freeing it if we find it and removing p's node
from the list. Of course, if we don't find p in the list, we do nothing.

That's when it struck me, I can pass anything to free() and if it's
not found in the list, nothing happens. No danger.

I added another function, 'void freeall(void);' to trip through the
list, freeing the allocations and the list nodes themselves, maybe
just before exiting your program.
 
C

CBFalconer

Joe said:
I never know where (or whether) to enter these incredible threads
but I do have something to share on the Subject.

Some time ago I determined to add 'size_t size(void *);' to my
otherwise meager bag of tricks.

In the simplist case, a call to malloc() is directed to a wrapper
that actually calls malloc but 'remembers' the size_t argument as
well as the void* return and saves them in a simple linked list.

A call to size(void *p) trips through the linked list looking for
the vallue of p and returns the size of the allocation if found,
else 0. Perfect.

Of course, I wrap free(void *p) as well. We trip through the list
looking for p and freeing it if we find it and removing p's node
from the list. Of course, if we don't find p in the list, we do nothing.

That's when it struck me, I can pass anything to free() and if it's
not found in the list, nothing happens. No danger.

I added another function, 'void freeall(void);' to trip through the
list, freeing the allocations and the list nodes themselves, maybe
just before exiting your program.

Er - what about realloc?
 
T

Tim Rentsch

Joe Wright said:
I never know where (or whether) to enter these incredible threads
but I do have something to share on the Subject.

Some time ago I determined to add 'size_t size(void *);' to my
otherwise meager bag of tricks.

In the simplist case, a call to malloc() is directed to a wrapper
that actually calls malloc but 'remembers' the size_t argument as
well as the void* return and saves them in a simple linked list.

A call to size(void *p) trips through the linked list looking for
the vallue of p and returns the size of the allocation if found,
else 0. Perfect.

Of course, I wrap free(void *p) as well. We trip through the list
looking for p and freeing it if we find it and removing p's node
from the list. Of course, if we don't find p in the list, we do nothing.

That's when it struck me, I can pass anything to free() and if it's
not found in the list, nothing happens. No danger.

I added another function, 'void freeall(void);' to trip through the
list, freeing the allocations and the list nodes themselves, maybe
just before exiting your program.

A nice technique. Thank you for sharing it.

By the way, if a hash table were used rather than a linked list, that
might add a little bit of memory usage, but would greatly speed up
both 'size()' and the 'free()' wrapper.

A binary tree would be another possibility; if this were done the
tree would likely need automatic rebalancing of some kind.
 
R

Ravi Uday

Joe Wright said:
Flash Gordon wrote:

[ snip ]

I never know where (or whether) to enter these incredible threads
but I do have something to share on the Subject.

Some time ago I determined to add 'size_t size(void *);' to my
otherwise meager bag of tricks.

In the simplist case, a call to malloc() is directed to a wrapper
that actually calls malloc but 'remembers' the size_t argument as
well as the void* return and saves them in a simple linked list.

A call to size(void *p) trips through the linked list looking for
the vallue of p and returns the size of the allocation if found,
else 0. Perfect.

Of course, I wrap free(void *p) as well. We trip through the list
looking for p and freeing it if we find it and removing p's node
from the list. Of course, if we don't find p in the list, we do nothing.

That's when it struck me, I can pass anything to free() and if it's
not found in the list, nothing happens. No danger.

So, if you call free() the node is removed from the linklist then and
there ?
Else, you might call free again on a freed pointer !! as in your freeall()
call
 
J

Joe Wright

Ravi said:
Flash Gordon wrote:

[ snip ]

I never know where (or whether) to enter these incredible threads
but I do have something to share on the Subject.

Some time ago I determined to add 'size_t size(void *);' to my
otherwise meager bag of tricks.

In the simplist case, a call to malloc() is directed to a wrapper
that actually calls malloc but 'remembers' the size_t argument as
well as the void* return and saves them in a simple linked list.

A call to size(void *p) trips through the linked list looking for
the vallue of p and returns the size of the allocation if found,
else 0. Perfect.

Of course, I wrap free(void *p) as well. We trip through the list
looking for p and freeing it if we find it and removing p's node
from the list. Of course, if we don't find p in the list, we do nothing.

That's when it struck me, I can pass anything to free() and if it's
not found in the list, nothing happens. No danger.


So, if you call free() the node is removed from the linklist then and
there ?

Exactly. The allocated memory is freed and then the node is removed
from the list and its memory is freed.
Else, you might call free again on a freed pointer !! as in your freeall()
call

No danger. free(p) first looks up p in the list. If p is not in the
list, nothing is done.
 
P

pete

Joe said:
No danger. free(p) first looks up p in the list.
If p is not in the list, nothing is done.

That's completely wrong, Joe.
Please help me debug my_program, it crashes.

/* BEGIN my_program.c */

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char *pointer = malloc(1);

if (pointer == NULL) {
puts("wow");
} else {
free(pointer);
free(pointer);
}
puts("OK");
return 0;
}

/* END my_program.c */
 
J

Joe Wright

pete said:
Joe Wright wrote:




That's completely wrong, Joe.
Please help me debug my_program, it crashes.

/* BEGIN my_program.c */

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char *pointer = malloc(1);

if (pointer == NULL) {
puts("wow");
} else {
free(pointer);
free(pointer);
}
puts("OK");
return 0;
}

/* END my_program.c */

You are missing the point. I have a header with..

#define malloc Malloc
#define free Free

...and another translation unit where Malloc and Free are defined so
that your program will call my routines.
 
C

CBFalconer

Joe said:
.... snip ...

You are missing the point. I have a header with..

#define malloc Malloc
#define free Free

..and another translation unit where Malloc and Free are defined
so that your program will call my routines.

That action is specifically forbidden by the standard when you
#include <stdlib.h>. The fact that it works for you is simply
luck (or lack of it) (or intimate knowledge of your system).

To illustrate the sort of thing that can go wrong, imagine you
have a file using strdup. It never uses stdlib.h, and thus the
code it calls calls the original malloc. The returned storage has
no connection with your added malloc control system. Now you pass
that storage about your system, and it finally gets freed in a
file that does use your redefinitions. The pointer is not found
and the free never occurs. Bingo, a memory leak. Just try to
find the cause.
 
K

Keith Thompson

CBFalconer said:
That action is specifically forbidden by the standard when you
#include <stdlib.h>. The fact that it works for you is simply
luck (or lack of it) (or intimate knowledge of your system).

To illustrate the sort of thing that can go wrong, imagine you
have a file using strdup. It never uses stdlib.h, and thus the
code it calls calls the original malloc. The returned storage has
no connection with your added malloc control system. Now you pass
that storage about your system, and it finally gets freed in a
file that does use your redefinitions. The pointer is not found
and the free never occurs. Bingo, a memory leak. Just try to
find the cause.

Note that strdup() is not a standard function. (At least it's not
defined by the C standard; it may be POSIX.)
 
J

Joe Wright

CBFalconer said:
Joe Wright wrote:

... snip ...



That action is specifically forbidden by the standard when you
#include <stdlib.h>. The fact that it works for you is simply
luck (or lack of it) (or intimate knowledge of your system).

To illustrate the sort of thing that can go wrong, imagine you
have a file using strdup. It never uses stdlib.h, and thus the
code it calls calls the original malloc. The returned storage has
no connection with your added malloc control system. Now you pass
that storage about your system, and it finally gets freed in a
file that does use your redefinitions. The pointer is not found
and the free never occurs. Bingo, a memory leak. Just try to
find the cause.

Chuck, I wish you and pete would cut me just a little slack. I've
been doing this stuff for almost twenty years. Not that I don't make
mistakes, but you usually have to look harder for them. The trick
works and works well and legally. Here's how..

Consider three files, main.c which is the user's program, ge.c which
is my set of functions and ge.h, a header to be included by main.c
in place of stdlib.h. ge.h defines main's normal calls to malloc,
realloc, calloc, free and strdup to Malloc, Realloc, Calloc, Free,
Strdup respectively.

This is the touchy ground. In producing object files and symbol
tables, are malloc and Malloc guaranteed to be different? On my
implementation they are but I don't find the guarantee.

ge.h also provides the prototypes of Malloc and friends.

Now there is the ge.c unit. It defines the functions Malloc,
Realloc, etc. and does include stdlib.h because realloc() will be
called from here, not from main.

I provide a makefile to hang all this stuff together.

My ge stuff (Garbage Eliminator) "Why collect garbage if you can
eliminate it?" is complete and tested.

If any of you have real interest in the code, ask me, either here or
in email.
 
C

CBFalconer

Joe said:
Chuck, I wish you and pete would cut me just a little slack. I've
been doing this stuff for almost twenty years. Not that I don't make
mistakes, but you usually have to look harder for them. The trick
works and works well and legally. Here's how..

That's why I included the underlined phrase above :) However it
is still illegal and inherently non-portable. Note that your
exposition doesn't include other modules not using your trick.
 
O

Old Wolf

Joe Wright said:
Chuck, I wish you and pete would cut me just a little slack. I've
been doing this stuff for almost twenty years. Not that I don't make
mistakes, but you usually have to look harder for them. The trick
works and works well and legally. Here's how..

But it isn't legal, that's the point. Your #defines above are
strictly forbidden by the standard, because they redefine the
name of a standard library function. You would only get
away with this if the client code did not include stdlib.h,
I think. (I won't go into the rationale for this). This is
easier said than done, because stdlib.h may be included by
some other header in a 3rd-party library that the project uses.

You would have been more portable if you had written your
Malloc, Free etc. functions and then required client code to
call those functions.

Chuck F raised a separate issue too: your scheme might leak memory
for pointers that point to memory allocated by any functions
in code that hasn't included "ge.h" (for example, strdup, or
those standard library functions which allocate memory).
Then if you call Free() on that pointer, it won't be in your list,
so you will never free() it. The client would have to take care
to call free() for some things and Free() for others. (Not that
this is a very strenuous requirement).
 
D

Dave Thompson

<snip> ge.h defines main's normal calls to malloc,
realloc, calloc, free and strdup to Malloc, Realloc, Calloc, Free,
Strdup respectively.

This is the touchy ground. In producing object files and symbol
tables, are malloc and Malloc guaranteed to be different? On my
implementation they are but I don't find the guarantee.
In C89 they weren't required to be; it allowed "external" symbols --
as they are usually called in crosslanguage object/linker/etc., in C
formally identifiers with external linkage -- to be implemented as
case insensitive and/or insignificant beyond 6 characters, but
categorized this as 'obsolescent', and C99 did indeed change it to
case sensitive and at least 32 characters. (Unlike K&R1 syntax, also
obsolescent in C89 but retained in C99, and implicit int and implicit
functions, removed in C99 although not deprecated in C89.)

The only case insensitive system I personally know of was RT-11, and
you'll have a hard time finding one of those now. In fact, to be a bit
crass about it, anyone who can keep one of those running today, or
reconstruct it, isn't likely to need your "crutch" :) :)

- David.Thompson1 at worldnet.att.net
 
A

ala

I have a situation where i want to free the memory pointed by a
pointer, only if it is not freed already. Is there a way to know
whether the memory is freed or not?

in the borland c 5.3 compiler *seems*
p=malloc(size);
<code_sinp>
if(p==0 || (p[-1]&0x1) ) printf("not allocated")
else printf("allocated");
 
A

ala

Ravi said:
Flash Gordon wrote:

[ snip ]

I never know where (or whether) to enter these incredible threads
but I do have something to share on the Subject.

Some time ago I determined to add 'size_t size(void *);' to my
otherwise meager bag of tricks.

In the simplist case, a call to malloc() is directed to a wrapper
that actually calls malloc but 'remembers' the size_t argument as
well as the void* return and saves them in a simple linked list.

A call to size(void *p) trips through the linked list looking for
the vallue of p and returns the size of the allocation if found,
else 0. Perfect.

Of course, I wrap free(void *p) as well. We trip through the list
looking for p and freeing it if we find it and removing p's node
from the list. Of course, if we don't find p in the list, we do nothing.

That's when it struck me, I can pass anything to free() and if it's
not found in the list, nothing happens. No danger.


So, if you call free() the node is removed from the linklist then and
there ?

Exactly. The allocated memory is freed and then the node is removed
from the list and its memory is freed.
Else, you might call free again on a freed pointer !! as in your freeall()
call

No danger. free(p) first looks up p in the list. If p is not in the
list, nothing is done.

wrong: it is an error, if debug mode it has to be reported
 
A

ala

in the borland c 5.3 compiler *seems*
p=malloc(size);
<code_sinp>
if(p==0 || ( ((unsigned*)p)[-1]&0x1 ) ) printf("not allocated")
else printf("allocated");
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top