C free

R

Reddy

Hello,

Can someone clarify this?

char *p = (char *) malloc (100*sizeof(char));
p=p+50;
free(p);

Does free clear all the 100 bytes of memory or only 50 as it is
pointing to 51st byte of memory now?

How are these malloc and free linked internelly?

Thanks,
Reddy
 
S

spibou

Reddy said:
Hello,

Can someone clarify this?

char *p = (char *) malloc (100*sizeof(char));
p=p+50;
free(p);

Does free clear all the 100 bytes of memory or only 50 as it is
pointing to 51st byte of memory now?

Neither ; it evokes undefined behaviour. You can only call free()
with either the NULL pointer or with a pointer which has a
value which was previously returned by malloc or similar functions.
How are these malloc and free linked internelly?

I'm not sure what you're asking here but I suspect it's up to
implementation.

Spiros Bousbouras
 
F

Flash Gordon

Neither ; it evokes undefined behaviour. You can only call free()
with either the NULL pointer or with a pointer which has a
value which was previously returned by malloc or similar functions.

In addition there are potential problems with the use of malloc. You
don't need to cast the return value of malloc (if the compiler complains
you have something else wrong) and sizeof(char) is 1 by definition so
its use is pointless. So the malloc call should be either

char *p = malloc(100 * sizeof *p);

or

char *p = malloc(100);

Search the group for lots of discussion on this point.
I'm not sure what you're asking here but I suspect it's up to
implementation.

I also suspect it is irrelevant to any properly written C program.
 
M

Malcolm

Reddy said:
Hello,

Can someone clarify this?

char *p = (char *) malloc (100*sizeof(char));
p=p+50;
free(p);

Does free clear all the 100 bytes of memory or only 50 as it is
pointing to 51st byte of memory now?

How are these malloc and free linked internelly?
The way malloc() works, on a simple system at least, is that there is a big
pool of memory.
Then we have a structure something like this

struct blockcontrol
{
blockcontrol *prev;
blockcontrol *next;
size_t length;
};

When you call malloc(), it finds a block of contiguous memory that is large
enough, and then it fills in the blockcontrol structure, so it knows how big
the allocated block is, and where the adjacent allocated free or allocated
blocks are. The precise details vary and we won't worry about them here.

Now comes the clever part. It returns a pointer to the memory immediately
after the block control structure it has filled out. The caller can then use
that memory as he likes.
When the caller calls free, the free function subtracts the size of a
blockcontrol structure from the pointer, and then it has access to all the
data. It can return the memory to the pool, merge consecutive free blocks,
and so on.

You will see that trying to free half the memory allocated, by passing a
pointer in the middle of the block allocated, will destroy this scheme.
free() won't be able to find the blockcontrol structure
 
G

Gordon Burditt

Can someone clarify this?
char *p = (char *) malloc (100*sizeof(char));
^^^^^^^^ this cast is useless.
p=p+50;
free(p);

Does free clear all the 100 bytes of memory or only 50 as it is
pointing to 51st byte of memory now?

free() is *NEVER* guaranteed to *CLEAR* memory. If you want
that, try memset().

If you pass a pointer to free() which you did not get from malloc()
or realloc(), you invoke the wrath of undefined behavior, which is
exactly what the above does. You might get a smegmentaion fault,
or it might spend all the money in your pocket.
How are these malloc and free linked internelly?

With chain-link fence?

Gordon L. Burditt
 
K

Keith Thompson

Reddy said:
Can someone clarify this?

char *p = (char *) malloc (100*sizeof(char));

Never cast the result of malloc(). It can mask certain errors, such
as failing to #include <stdlib.h>. Preferred:

char *p = malloc(100 * sizeof *p);

or, since sizeof(char) is 1 by definition:

char *p = malloc(100);

Always check whether malloc succeeded. (It returns NULL if it fails.)

Undefined behavior of malloc() failed.

Kaboom!

free() may only be called with the result of a previous malloc() (or
calloc() or realloc()) or with a null pointer. Anything else causes
undefined behavior, and is very likely to mess things up quite
thoroughly.
Does free clear all the 100 bytes of memory or only 50 as it is
pointing to 51st byte of memory now?

free() doesn't clear memory; it deallocated it (i.e., makes it
available for later allocation). The contents of the memory are
indeterminate.
How are these malloc and free linked internelly?

As if by magic. The runtime system maintains internal information to
enable it to allocate and deallocate memory. How it does this is
entirely up to the implementation, and varies from one system to
another. The functions work as described in the standard; that's all
you know, and if you happen to know the internal details, you
shouldn't depend on them.
 
P

pete

Keith Thompson wrote:
free() doesn't clear memory; it deallocated it (i.e., makes it
available for later allocation). The contents of the memory are
indeterminate.

The freed pointer value itself is indeterminate.
The memory in question, is no longer an object.
 
K

Kenny McCormack

The freed pointer value itself is indeterminate.
The memory in question, is no longer an object.

Which is probably a good thing. It was getting tired of being treated
like an object.
 
W

Walter Roberson

Malcolm said:
When you call malloc(), it finds a block of contiguous memory that is large
enough, and then it fills in the blockcontrol structure, so it knows how big
the allocated block is, and where the adjacent allocated free or allocated
blocks are. The precise details vary and we won't worry about them here.
Now comes the clever part. It returns a pointer to the memory immediately
after the block control structure it has filled out. The caller can then use
that memory as he likes.
When the caller calls free, the free function subtracts the size of a
blockcontrol structure from the pointer, and then it has access to all the
data. It can return the memory to the pool, merge consecutive free blocks,
and so on.

Implementation details that are not true in all systems.
 
C

Charles Richmond

Reddy said:
Hello,

Can someone clarify this?

char *p = (char *) malloc (100*sizeof(char));
p=p+50;
free(p);

Does free clear all the 100 bytes of memory or only 50 as it is
pointing to 51st byte of memory now?
By freeing a pointer that was *not* returned by "malloc()", you
have evoked undefined behavior.

The C standard *not* withstanding, I can pretty much guarantee you
that by freeing "p=p+50", you have royally trashed out the workings
used by "malloc()".
How are these malloc and free linked internelly?
How "malloc()" and "free()" work internally is implementation
dependent. Different implementations are free to do it in
different ways and still be compliant with the standard.
 
T

Thad Smith

pete said:
The freed pointer value itself is indeterminate.

I expect it to be the same value that it was last assigned. Why do you
think it is indeterminate?
 
K

Keith Thompson

Thad Smith said:
I expect it to be the same value that it was last assigned. Why do
you think it is indeterminate?

Because the standard says so.

C99 6.2.4p2:

The value of a pointer becomes indeterminate when the object it
points to reaches the end of its lifetime.

I would expect, in most implementations, that the pointer passed to
free() will retain its previous representation (it's been argued that
this is required), and that it will compare equal to a saved copy of
its value from before the call to free(). More concretely:

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

int main(void)
{
int *ptr = malloc(sizeof *ptr);
int *saved_ptr = ptr;
if (ptr == NULL) {
printf("malloc failed\n");
}
else {
free(ptr);
if (ptr == saved_ptr) {
printf("equal\n");
}
else {
printf("not equal\n");
}
}
return 0;
}

I would be surprised if this program printed "not equal" in any
implementation, but the standard permits it to do so -- or to print
"fnord", for that matter.
 
E

Eric Sosman

Thad said:
I expect it to be the same value that it was last assigned. Why do you
think it is indeterminate?

Perhaps because he has read the Standard. Specifically,
section 6.2.4 paragraph 2:

[...] The value of a pointer becomes indeterminate
when the object it points to reaches the end of
its lifetime.

Already I hear your plaintive cry: "Well, so, but why?"

On many machines, the value of a pointer is an address
and the value has meaning whether or not the memory at that
address is "occupied" by any of the program's objects. But
at a little more abstract level, the value of a pointer is
a reference to an object -- and if there is no object, there
can be no reference to it. A pointer that once pointed to an
object thus loses its value when the object ceases to exist.

Here is a pointer: "The last paragraph on the seventeenth
page of the fourth book on the fifth shelf in the second room
on the right as you come through the main entrance of the City
Library." It's a pointer because it's a reference, and using
the reference you can look up what it refers to.

Alas! The City is Alexandria and the Library was burned
multiple times by multiple conquerors many centuries ago. The
above is no longer a reference, but just a string of useless
words -- in fact, "valueless" words.

"514 Elm Street" looks like it might be an address, and
you might write it on an envelope. But if the space between
512 and 516 is a vacant lot, will the Post Office deliver
that letter? No: They will return it to you as undeliverable,
and might even mark it "No such address."

C's model of storage allows for addresses that carry more
"structure" than simple numbers. Most machines today do not
take advantage of this freedom, but who knows what will come
tomorrow? If tomorrow brings structured addresses, C will be
ready for them.
 
R

Reddy

Thank you all for your responses...

Regards,
Reddy


Eric said:
Thad said:
I expect it to be the same value that it was last assigned. Why do you
think it is indeterminate?

Perhaps because he has read the Standard. Specifically,
section 6.2.4 paragraph 2:

[...] The value of a pointer becomes indeterminate
when the object it points to reaches the end of
its lifetime.

Already I hear your plaintive cry: "Well, so, but why?"

On many machines, the value of a pointer is an address
and the value has meaning whether or not the memory at that
address is "occupied" by any of the program's objects. But
at a little more abstract level, the value of a pointer is
a reference to an object -- and if there is no object, there
can be no reference to it. A pointer that once pointed to an
object thus loses its value when the object ceases to exist.

Here is a pointer: "The last paragraph on the seventeenth
page of the fourth book on the fifth shelf in the second room
on the right as you come through the main entrance of the City
Library." It's a pointer because it's a reference, and using
the reference you can look up what it refers to.

Alas! The City is Alexandria and the Library was burned
multiple times by multiple conquerors many centuries ago. The
above is no longer a reference, but just a string of useless
words -- in fact, "valueless" words.

"514 Elm Street" looks like it might be an address, and
you might write it on an envelope. But if the space between
512 and 516 is a vacant lot, will the Post Office deliver
that letter? No: They will return it to you as undeliverable,
and might even mark it "No such address."

C's model of storage allows for addresses that carry more
"structure" than simple numbers. Most machines today do not
take advantage of this freedom, but who knows what will come
tomorrow? If tomorrow brings structured addresses, C will be
ready for them.
 
G

Guest

Keith said:
I would expect, in most implementations, that the pointer passed to
free() will retain its previous representation (it's been argued that
this is required),

The standard explicitly allows representations to change during writes,
but not explicitly during reads, and since every object can be accessed
as an array of unsigned char, where each element is itself an object
which must "[retain] its last-stored value throughout its lifetime", I
would've thought this is required.

However, according to
http://open-std.org/JTC1/SC22/WG14/www/docs/dr_260.htm
it is not. I'm not sure what to say about it, though, other than that
another part of the response already directly contradicts the standard:

"If two objects have identical bit-pattern representations and their
types are the same they may still compare as unequal [...]"

6.2.6.1#4: "Two values (other than NaNs) with the same object
representation compare equal,"

"[...] (for example if one object has an indeterminate value) and if
one is an indeterminate value attempting to read such an object invokes
undefined behavior."

If either is an indeterminate value, the behaviour is undefined before
any comparison is made. This means indeterminate values are not an
example of the above.
 
S

spibou

Eric said:
Thad said:
I expect it to be the same value that it was last assigned. Why do you
think it is indeterminate?

Perhaps because he has read the Standard. Specifically,
section 6.2.4 paragraph 2:

[...] The value of a pointer becomes indeterminate
when the object it points to reaches the end of
its lifetime.

Already I hear your plaintive cry: "Well, so, but why?"

On many machines, the value of a pointer is an address
and the value has meaning whether or not the memory at that
address is "occupied" by any of the program's objects. But
at a little more abstract level, the value of a pointer is
a reference to an object -- and if there is no object, there
can be no reference to it. A pointer that once pointed to an
object thus loses its value when the object ceases to exist.

Here is a pointer: "The last paragraph on the seventeenth
page of the fourth book on the fifth shelf in the second room
on the right as you come through the main entrance of the City
Library." It's a pointer because it's a reference, and using
the reference you can look up what it refers to.

Alas! The City is Alexandria and the Library was burned
multiple times by multiple conquerors many centuries ago. The
above is no longer a reference, but just a string of useless
words -- in fact, "valueless" words.

"514 Elm Street" looks like it might be an address, and
you might write it on an envelope. But if the space between
512 and 516 is a vacant lot, will the Post Office deliver
that letter? No: They will return it to you as undeliverable,
and might even mark it "No such address."

Consider the following programme:

#include <stdio.h>

int *p ;

void foo(void) {
int a ;

p = &a ;
}

int main() {

foo() ;
printf("p is %p\n",p) ;
}

Is this undefined behaviour ?

Spiros Bousbouras
 
V

Vladimir Oka

Consider the following programme:

#include <stdio.h>

int *p ;

void foo(void) {
int a ;

p = &a ;
}

int main() {

foo() ;
printf("p is %p\n",p) ;
}

Is this undefined behaviour ?

Probably, as "%p" requires `void *`. ;-)

If you fix that (by casting to `void *`), I don't think it is.
Trying to print `*p` would be though (with "%d", obviously).

It's the dereferencing the dud pointer that causes UB, not accessing
it's value.
 
K

Keith Thompson

Vladimir Oka said:
Probably, as "%p" requires `void *`. ;-)

If you fix that (by casting to `void *`), I don't think it is.
Trying to print `*p` would be though (with "%d", obviously).

It's the dereferencing the dud pointer that causes UB, not accessing
it's value.

Yes, it's undefined behavior. As I mentioned elsethread, C99 6.2.4p2
says:

The value of a pointer becomes indeterminate when the object it
points to reaches the end of its lifetime.

You're very likely to get away with this, but any attempt to even look
at the value of an indeterminate pointer invokes undefined behavior.
 
F

Flash Gordon

Vladimir said:
Probably, as "%p" requires `void *`. ;-)

If you fix that (by casting to `void *`), I don't think it is.
Trying to print `*p` would be though (with "%d", obviously).

It's the dereferencing the dud pointer that causes UB, not accessing
it's value.

No, even accessing it can cause UB. Section 6.2.4 para 2 of N1124 says:

| The lifetime of an object is the portion of program execution during
| which storage is guaranteed to be reserved for it. An object exists,
| has a constant address,25) and retains its last-stored value
| throughout its lifetime.26) If an object is referred to outside of its
| lifetime, the behavior is undefined. The value of a pointer becomes
| indeterminate when the object it points to reaches the end of its
| lifetime.

So the pointer becomes indeterminate. An indeterminate value is either
an unspecified value or a trap representation, and if it is a trap
reading it is UB.
 
V

Vladimir Oka

Keith said:
Yes, it's undefined behavior. As I mentioned elsethread, C99 6.2.4p2
says:

The value of a pointer becomes indeterminate when the object it
points to reaches the end of its lifetime.

You're very likely to get away with this, but any attempt to even look
at the value of an indeterminate pointer invokes undefined behavior.

Hmm. The Standard obviously makes a difference between UB and
`indeterminate` value, as the sentence just before the one you quote
explicitely says that trying to refer to an object after its lifetime
ends invokes UB (to losely paraphrase). The whole paragraph is:

The lifetime of an object is the portion of program execution during
which
storage is guaranteed to be reserved for it. An object exists, has a
constant
address, and retains its last-stored value throughout its lifetime.
If an object
is referred to outside of its lifetime, the behavior is undefined.
The value of a
pointer becomes indeterminate when the object it points to reaches
the end
of its lifetime.

I'm inclined to interpret "indeterminate" more as "you may get
unexpected values on inspection" than "even looking invokes UB".
Probably something along the lines of Schroedinger's cat (apologies for
likely misspelling of the great man's name).
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,184
Messages
2,570,978
Members
47,561
Latest member
gjsign

Latest Threads

Top