...malloc ...from Rome :-)

L

lasek

Hi all..i'm here another time..for a simple question:

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

int main(void)
{
/*
** I know that someone else use different malloc
** instruction
*/

int *pInt=(int*)malloc(1*sizeof(pInt));

if(pInt)
{
printf("Memory allocated SUCCESS [%p]\n",pInt);
free(pInt);
}

printf("Release memory previously allocated [%p]\n",pInt);

/*
** Why i can see the same address once that i've released?
*/

return 0;
}

Thanks all and have a nice day(???)...
 
N

Nicolas Pavlidis

lasek said:
Hi all..i'm here another time..for a simple question:

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

int main(void)
{
/*
** I know that someone else use different malloc
** instruction
*/

int *pInt=(int*)malloc(1*sizeof(pInt));

if(pInt)
{
printf("Memory allocated SUCCESS [%p]\n",pInt);
free(pInt);
}

printf("Release memory previously allocated [%p]\n",pInt);

/*
** Why i can see the same address once that i've released?
*/

The addres will not be removed by free(), only the memory pInt points to
will be freed after the call. It can even happen, that you can access
the memory which was already freed, but this depends on the operatin
system.

Kind regrads,
Nicolas
 
J

Jonathan Adams

"lasek said:
Hi all..i'm here another time..for a simple question:

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

int main(void)
{
/*
** I know that someone else use different malloc
** instruction
*/

int *pInt=(int*)malloc(1*sizeof(pInt));

This is bogus -- the (int*) cast is unneeded, and the sizeof()
expression is wrong. It should be:

int *pInt = malloc(1 * sizeof (*pInt));

if(pInt)
{
printf("Memory allocated SUCCESS [%p]\n",pInt);
free(pInt);
}

printf("Release memory previously allocated [%p]\n",pInt);

This provokes undefined behavior -- you may not reference the value of
pInt in any way after it has been passed to free().

Cheers,
- jonathan
 
J

James Stevenson

This is bogus -- the (int*) cast is unneeded, and the sizeof()
expression is wrong. It should be:

int *pInt = malloc(1 * sizeof (*pInt));

if(pInt)
{
printf("Memory allocated SUCCESS [%p]\n",pInt);
free(pInt);
}

printf("Release memory previously allocated [%p]\n",pInt);

This provokes undefined behavior -- you may not reference the value of
pInt in any way after it has been passed to free().

Actually its not.

if you define int *p;
it is perforectly ok to access p but not ok to access *p
after the free is performed.

Also what you seem to impliy is that the value of p
will change once passed to the function free. This is also
not true. Only the memory address that p points to may / may not be
changed. The actually value of p will remain constant.

James
 
T

Thomas Stegen

James said:
Also what you seem to impliy is that the value of p
will change once passed to the function free. This is also
not true. Only the memory address that p points to may / may not be
changed. The actually value of p will remain constant.

1) The value of a pointer variable after a call to free is
indeterminate.
2) Evaluating a variable with a indeterminate value is undefined.

This might seem strange, but the standard is quite clear about
both points above. Can't dig out the quotes just now, but unless
someone else posts them I'll do it later today or tomorrow.

There was a big discussion about this some time ago, maybe google
will have some details.
 
C

Chris Torek

if you define int *p;
it is perforectly ok to access p but not ok to access *p
after the free is performed.

The Standard says otherwise.
Also what you seem to impliy is that the value of p
will change once passed to the function free. This is also
not true. Only the memory address that p points to may / may not be
changed. The actually value of p will remain constant.

Well, sort of.

The *bit pattern* stored in p will not be changed -- but the *value*
of p might change.

Here is a News Rerun.

From: Chris Torek <[email protected]>
Newsgroups: comp.lang.c
Subject: Re: Malloc/Free - freeing memory allocated by malloc
Date: 23 Sep 2004 01:01:48 GMT
Message-ID: <[email protected]>
References: said:
(e-mail address removed)-berlin.de wrote: [after]
int *x = malloc( 100 * sizeof *x );
....
free( x );

Both the following lines would invoke undefined behavior.

printf( "%d %d\n", x[ 11 ], *( x + 42 ); /* wrong! */
printf( "%p\n", ( void * ) x ); /* wrong! */

I have a question about this [second] line, printing the value of 'x'.
Why is this wrong? The memory allocated [for] x is on the function stack,
and I didn't believe you are accessing any invalid memory region?

Let me back things up a bit. Suppose instead of "int *x" or even
"int y", or "float z", I tell you only that I have four bytes in
memory that are set to 0x12, 0x34, 0x56, and 0x78 in sequence.

What is the value stored in this four-byte region? Is it 0x12345678?
Is it perhaps 0x78563412? Or could it even be something like
17378244361449504001963252426735616.0?

The answer is: it depends. Those four bytes are, as a 32-bit int,
the first value (0x12345678) on a SPARC or 680x0-based machine,
but the second (0x78563412) on an Intel x86-based machine. The
third (1.73782e34, or 7019017 * pow(2,91)) occurs if those four
bytes are meant to be interpreted as a 32-bit floating point number
on the x86.

Clearly, then, the value of some sequence of bytes depends on the
*interpretation* of that byte-sequence. The next question I would
like to ask, then, is this: How are the bytes making up a pointer
interpreted?

On many machines, they happen to be interpreted in precisely the
same way as some integer; but this is not the only possible
interpretation. Those who used the x86 in its early 80186 and
80286 incarnations should remember the "1-megabyte pointer", in
which the upper 16 bits represented the top 16 of the 20 bits of
the address, and the lower 16 bits represented the bottom 16 of
the 20 bits of the address, with those two values being summed:

real_20_bit_address = ((upper_16(ptr) << 4) + lower_16(ptr)) & 0xfffff;

(This means that any given physical address has lots of different
32-bit values that refer to it. This particular "feature" was the
source of a lot of problems and the term "pointer normalization".
It is also one reason that the C standards define "a < b" only for
pointers a and b into a single object, while "a == b" is defined
even if a and b point to different objects -- the equality operators
must normalize their pointers, while the relational operators are
allowed to compare only the offsets.)

Yet another interpretation was allowed on some varieties of the
x86, in which the upper 16 bits of the pointer were an index into
an (external) table, and the lower 16 bits were an offset to be
applied to the result of the table:

real_NN_bit_address = table[upper_16(ptr)] + lower_16(ptr);
/* more or less */

All of these interpretations -- and indeed almost any other
interpretation anyone can think of yesterday, today, or tomorrow
-- are allowed (but not required) by the C standard. The last of
the above, with the table-lookup step, happens to allow something
else the x86 did: the table need not contain just a "base address".
It can also contain a "valid" flag:

if (table[upper_16(ptr)].valid == 0)
throw_runtime_error("invalid address");
real_NN_bit_address = table[upper_16(ptr)].base + lower_16(ptr);

Now, all free() needs to do is contain, as one of its steps:

table[upper_16(ptr)].valid = 0;

and suddenly a bit pattern that *was* valid, before the call to
free(), is no longer valid. An attempt to print it, which used
to work, may now cause a runtime "invalid address" error.

The bit pattern has not changed. What changed is the external
table. The C standard allows this, and tells you -- the C programmer
-- not to attempt to use the value in x after passing that value
to free(), just in case free() cleared the table's "valid" bit.

Of course, as Jens wrote, you *are* allowed to overwrite x with a
new value, or with NULL. Any C compiler must make sure this works,
even if it has this kind of "valid/invalid table entry" action that
goes on with malloc() and free().

This is all part of a more fundamental issue, which C programmers
in particular should consider, because C has "C bytes" that can be
used to access hardware-level "representations" instead of
language-level "values". That issue is: the *representation* of
a value, and value itself, are different things. Values arise
through *interpretation* of some bit pattern (a "representation"),
and the process of interpretation can be quite complex. We see
this now, today, on conventional architectures, only in floating-point
numbers -- but in the past, we saw such things elsewhere. There
were good reasons for complicated interpretations for pointers,
and those reasons may well recur in the future.

["Methods of interpretation" are also the reason we see byte-order
issues in integers. If some entity takes a long string of bits
and breaks it up into groups of, say, 8 at a time, it is that entity
that chooses which order to put out the groups, and then to
re-assemble them for later re-interpretation as a larger group.
Any given machine may have its own method(s) for splitting and
combining to get 8-bit groups, but if you, as a C programmer, deal
in terms of (integral) *values*, and do your own splitting and
combining, *you* can control the results, rather than being at the
mercy of your machine(s).]
 
K

Keith Thompson

James Stevenson said:
This is bogus -- the (int*) cast is unneeded, and the sizeof()
expression is wrong. It should be:

int *pInt = malloc(1 * sizeof (*pInt));

if(pInt)
{
printf("Memory allocated SUCCESS [%p]\n",pInt);
free(pInt);
}

printf("Release memory previously allocated [%p]\n",pInt);

This provokes undefined behavior -- you may not reference the value of
pInt in any way after it has been passed to free().

Actually its not.

Actually it is.
if you define int *p;
it is perforectly ok to access p but not ok to access *p
after the free is performed.

No, accessing the value of p after free(p) invokes undefined behavior.
Also what you seem to impliy is that the value of p
will change once passed to the function free. This is also
not true. Only the memory address that p points to may / may not be
changed. The actually value of p will remain constant.

The value doesn't necessarily change (in fact I would argue that the
value, or at least its representation, *can't* change), but the value
becomes indeterminate. On most real-world systems, the resulting
undefined behavior is harmless (the worst kind), but it's
theoretically possible that, for example, an attempt to load the value
into an address register will cause a trap.
 
L

lasek

post...in effect before post this question, it should be better to read
others post..

The post from Chris Torek is very exaustive...

But now i've another doubt:

if i have an expression like this:

struct agenda
{
char acNome[20];
struct agenda *next;
};

typedef struct agenda lista_agenda;

lista_agenda *start=NULL;

start=(lista_agenda *)malloc(sizeof(lista_agenda));

/*
** void *malloc(size_t size);
*/
...i need to cast the result from malloc and i don't need to put the
operator '*' inside the sizeof [sizeof(lista_agenda*)]...because i need a
pointer variable to point to a "lista_agenda type".Because if i put the
'*'..with gdb i see a crash when try to strncpy the first members:
"Program received signal SIGSEGV, Segmentation fault.
0x4207aecc in chunk_free () from /lib/i686/libc.so.6"

Is correct ?.

Best regards from Rome.
 
M

Mike Wahler

free(pInt);
}

printf("Release memory previously allocated [%p]\n",pInt);

This provokes undefined behavior -- you may not reference the value of
pInt in any way after it has been passed to free().

Actually its not.

if you define int *p;
it is perforectly ok to access p but not ok to access *p
after the free is performed.

I used to believe that too -- until I came to clc and
the kind folks here straightened me out. :)
Also what you seem to impliy is that the value of p
will change once passed to the function free. This is also
not true.

No, in itself that's not necessarily true. What *is* true
is that the standard specifically states that the result
of evaluating its value is undefined behavior.
Only the memory address that p points to may / may not be
changed. The actually value of p will remain constant.

It might, it might not. But that doesn't matter.

-Mike
 
M

Mike Wahler

lasek said:
post...in effect before post this question, it should be better to read
others post..

The post from Chris Torek is very exaustive...

Yes, and sometimes I find reading his stuff to
be exhausting :), but always worthwhile.
But now i've another doubt:

if i have an expression like this:

struct agenda
{
char acNome[20];
struct agenda *next;
};

typedef struct agenda lista_agenda;

lista_agenda *start=NULL;

start=(lista_agenda *)malloc(sizeof(lista_agenda));

Stop doing that (casting return value of 'malloc()').
It only can serve to hide a serious error (omitting
'malloc()'s declaration).

#include <stdlib.h> /* make sure this is at the beginning of your file */
/* etc */
start = malloc(sizeof *start);
/*
** void *malloc(size_t size);
*/
..i need to cast the result from malloc

No, you do *not*.
and i don't need to put the
operator '*' inside the sizeof [sizeof(lista_agenda*)]

The expression 'sizeof(lista_agenda*)' will give the
number of bytes occupied by a pointer (specifically the
size of type 'lista_agenda *'). Not the size of 'struct
agenda'.
...because i need a
pointer variable to point to a "lista_agenda type".

'malloc()' returns a pointer to the allocated memory.
Assign it (directly) to 'start'. Then it does indeed
point to an (uninitialized) object of type 'struct agenda'.
No cast is needed. A pointer to void can be converted to
any other pointer type (and back again if desired). The
language standard specifically states this.
Because if i put the
'*'..with gdb i see a crash when try to strncpy the first members:

"I put the '*'", is not specific enough to describe
exactly what you're doing.
"Program received signal SIGSEGV, Segmentation fault.
0x4207aecc in chunk_free () from /lib/i686/libc.so.6"

Show us the *exact* code that produces this behavior.
Is correct ?.
No.


Best regards from Rome.

Um, it seems today I should not "do as the Romans do." :)

-Mike
 
M

Mark McIntyre

But now i've another doubt:

start=(lista_agenda *)malloc(sizeof(lista_agenda));

..i need to cast the result from malloc

No you don't,. A C compiler is obliged to ensure that the memory returned
by malloc automatically matches the type you assign it to.
and i don't need to put the
operator '*' inside the sizeof [sizeof(lista_agenda*)]...because i need a
pointer variable to point to a "lista_agenda type".

Yes. To avoid this confusion, use the idiom:

start = malloc(sizeof *start);
Because if i put the
'*'..with gdb i see a crash when try to strncpy the first members:
"Program received signal SIGSEGV, Segmentation fault.
0x4207aecc in chunk_free () from /lib/i686/libc.so.6"

You have a bug somewhere else in your code. For example, you're corrupting
the memory in your struct, or you're trying to free it twice.
Is correct ?.

No
 
J

James Stevenson

That is, strictly speaking, incorrect. See

http://www.eskimo.com/~scs/C-faq/q7.21.html

erm thats for the resource it just backs up my statement.

Quote:

Why isn't a pointer null after calling free?
How unsafe is it to use (assign, compare) a pointer value after it's been
freed?

The contents of p are still valid where the contents of where p point are
no unpredictable. Hence p is still completly valid.

as in

func() {
int *p = malloc(sizeof(*p));
if (!p)
bomb();
free(p);
p = (int *) 0;
}

Is perfrectly valid to write.
however *p = 0; after the free would be of course dangerour and
unpredicatable.

The local variable p as a point is not changed by free in any way.

James
 
J

James Stevenson

I used to believe that too -- until I came to clc and
the kind folks here straightened me out. :)


No, in itself that's not necessarily true. What *is* true
is that the standard specifically states that the result
of evaluating its value is undefined behavior.


It might, it might not. But that doesn't matter.

then this would dictate that free is not a function but a macro
otherwise it has no way of changing the value of p directly.

Last time i check free was a function not a macro or did i mis something.
but of course the contents of p probably are not usefull in any case after
free has been called :)

James
 
M

Mike Wahler

James Stevenson said:
then this would dictate that free is not a function but a macro
No.

otherwise it has no way of changing the value of p directly.

Note that the language standard does not prohibit 'magic' (or anything
else) as an implementation method. Behavior is what is specified
(or specifically left 'undefined' or 'implementation-defined', etc.)
The 'pass-by-value' semantics of C don't necessarily apply in this
case. This is why the explicit verbiage of the standard.
("or if the space has been deallocated by a call to free or realloc,
the behavior is undefined.")
Last time i check free was a function not a macro or did i mis something.

It's a function (but whose internal operational details are
left to the implementation).
but of course the contents of p probably are not usefull

Not just not useful, not defined. A particular implementation
might choose to define and/or use this "value" in some way, but
such usage falls outside the domain of the standard language/library.
in any case after
free has been called :)

Right. Thus the practice by many of assigning NULL to the pointer
immediately after 'free()' (some wrap 'free' in a macro for this
purpose), so they can inspect its value before subsequent use.
Treat a pointer passed to 'free()' as you would an uninitialized
object, i.e. "no peeking" (but of course you're free :) to assign
it a new value).


-Mike
 
C

Christopher Benson-Manica

James Stevenson said:
erm thats for the resource it just backs up my statement.

A careful reading reveals the opposite:

"A pointer value which has been freed is, strictly speaking, invalid,
and any use of it, even if is not dereferenced can theoretically
lead to trouble..."

The key portion is "even if it is not dereferenced"; IOW, the value of
the pointer may not be used in any way once it has been passed to
free(). Specifically, it may not be passed to the printf as an
argument for the %p conversion specifier, as in the OP's code:

if(pInt)
{
printf("Memory allocated SUCCESS [%p]\n",pInt);
free(pInt);
}

printf("Release memory previously allocated [%p]\n",pInt);

While the FAQ notes that on reasonable implementations it is likely
to be altogether harmless, the code as written exhibits undefined
behavior (as other more learned posters have also pointed out).
Therefore your original statement:

"t is perforectly ok to access p but not ok to access *p after the
free is performed."

is incorrect. Of course, the code you supplied
func() {
int *p = malloc(sizeof(*p));
if (!p)
bomb();
free(p);
p = (int *) 0;
}

is correct; the value of the freed pointer is not used. However, it
does contain an unnecessary cast of 0 to (int *); 0 in a pointer
context is guaranteed to yield the same value as the macro NULL.
 
M

Mike Wahler

James Stevenson said:
erm thats for the resource it just backs up my statement.
Huh?

Quote:

Why isn't a pointer null after calling free?
How unsafe is it to use (assign, compare) a pointer value after it's been
freed?

The contents of p are still valid where the contents of where p point are
no unpredictable. Hence p is still completly valid.

as in

func() {
int *p = malloc(sizeof(*p));
if (!p)
bomb();
free(p);
p = (int *) 0;
}

Is perfrectly valid to write.
however *p = 0; after the free would be of course dangerour and
unpredicatable.

The local variable p as a point is not changed by free in any way.

That is not what appears at that URL. This is:


============ begin quote ================================

Question 7.21

Why isn't a pointer null after calling free?
How unsafe is it to use (assign, compare) a pointer value after it's been
freed?

----------------------------------------------------------------------------
----

When you call free, the memory pointed to by the passed pointer is freed,
but the value of the pointer in the caller remains unchanged, because C's
pass-by-value semantics mean that called functions never permanently change
the values of their arguments. (See also question 4.8.)

A pointer value which has been freed is, strictly speaking, invalid, and any
use of it, even if is not dereferenced can theoretically lead to trouble,
though as a quality of implementation issue, most implementations will
probably not go out of their way to generate exceptions for innocuous uses
of invalid pointers.

References: ANSI Sec. 4.10.3
ISO Sec. 7.10.3
Rationale Sec. 3.2.2.3


This page by Steve Summit // Copyright 1995

============ end quote ================================


This does seem to indicate that a (valid, evaluable) expression
can switch from 'valid' to 'invalid' without it's 'value' having
changed. The standard appears to allow this, which imo it has every
right to do, being the definition of how things behave (there
are many stated exceptions to certain behaviors scattered throughout).
However the second paragraph does clearly state the actual facts.

Perhaps you're looking at some other 'FAQ' or an older,
incorrect version of this one and failed to refresh your
browser cache?


-Mike
 
J

Jonathan Adams

James Stevenson said:
erm thats for the resource it just backs up my statement.

Quote:

Why isn't a pointer null after calling free?
How unsafe is it to use (assign, compare) a pointer value after it's been
freed?

The contents of p are still valid where the contents of where p point are
no unpredictable. Hence p is still completly valid.

Read that second question again -- it is talking about the *value* of
the pointer, not what the pointer points at.
as in

func() {
int *p = malloc(sizeof(*p));
if (!p)
bomb();
free(p);
p = (int *) 0;
}

Is perfrectly valid to write.

Yes. No one has said that otherwise (you're overwriting the value of p,
not using it)
however *p = 0; after the free would be of course dangerour and
unpredicatable.

Yes. The standard also says that:

char *q;

free(p);
q = p; /* undefined */
if (p != NULL) /* undefined */
/* ... */

leads to undefined behavior.
The local variable p as a point is not changed by free in any way.

Indeed it isn't. That doesn't mean it is safe to use its value.

Cheers,
- jonathan
 
K

Keith Thompson

James Stevenson said:
erm thats for the resource it just backs up my statement.

Um, no it doesn't.
Quote:

Why isn't a pointer null after calling free?
How unsafe is it to use (assign, compare) a pointer value after it's been
freed?

The contents of p are still valid where the contents of where p point are
no unpredictable. Hence p is still completly valid.

Nope. FAQ 7.21 says:

A pointer value which has been freed is, strictly speaking,
invalid, and any use of it, even if is not dereferenced can
theoretically lead to trouble, though as a quality of
implementation issue, most implementations will probably not go
out of their way to generate exceptions for innocuous uses of
invalid pointer
as in

func() {
int *p = malloc(sizeof(*p));
if (!p)
bomb();
free(p);
p = (int *) 0;
}

Is perfrectly valid to write.
however *p = 0; after the free would be of course dangerour and
unpredicatable.

Yes, the above is perfectly valid, since it doesn't access the value
of p after the call to free().

It's important to distinguish between an object (p in this case) and
the current value of an object. After free(p), p is still a pointer
object, and you can take its address or assign a value to it. You can
do anything that doesn't examine the value stored in p. But if you do
examine its value, you invoke undefined behavior. So the following is
ok:

int *p = malloc(sizeof *p);
free(p); /* valid whether malloc succeeded or not */
p = NULL;

but this is not:

int *p = malloc(sizeof *p);
free(p);
if (p == NULL) ...
The local variable p as a point is not changed by free in any way.

The bits making up the value of p don't change; what changes is
whether the value is indeterminate.

With a few system-specific assumptions:

int *p = malloc(sizeof *p);
/*
* Assume that malloc succeeded, and that the value stored in p
* is represented as 0x12345678; this is the address of the
* allocated memory. (int*)0x12345678 is now a valid pointer
* value.
*/
free(p);
/*
* This informs the system that we're finished with the memory
* allocated by malloc(). It doesn't change the representation of
* the value of p, but that unchanged value has become
* indeterminate. (int*)0x12345678 is now an indeterminate
* pointer value. An attempt to dereference it obviously invokes
* undefined behavior. Less obviously, but just as true, an
* attempt to examine the value, such as (p == NULL), also invokes
* undefined behavior. You can still retrieve the representation
* by aliasing p with an array of unsigned char, but there's
* little reason for doing so.
*/
 
K

Keith Thompson

Mark McIntyre said:
No you don't,. A C compiler is obliged to ensure that the memory returned
by malloc automatically matches the type you assign it to.

It's true that you don't need the cast, but your explanation is a bit
off.

malloc doesn't return the allocated memory, it returns a pointer to
it. The allocated memory is guaranteed to be suitably aligned for any
type of object, but that's not why the cast is unnecessary. The cast
is unnecessary because malloc returns a result of type void*, and a
value of type void* can be implicitly converted to any
pointer-to-object type. (The suitable alignment is what makes the
result useful.)
 

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

Similar Threads

Alternative to Malloc in C 0
Open letter to Ian Collins 32
malloc 40
C + Malloc 8
Breakthrough 25
Fibonacci 0
malloc and maximum size 56
STRING - Remove small letters from string 1

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top