Please clear my doubt

Y

Yang Lee

Hi All,
I have two char pointers

char *a,*b;
a=(char *)malloc(10);
b=a; /*******/

so both pointers are looking at same mamory location

strcpy(a,"gates");
printf("%s",b);

Now I free pointer b;
free(b);

Then will pointer a be in existance or it will be also freed.
or if I free pointer a then will b point to same location.

Also

a=(char *)malloc(10);
strcpy(a,"gates");
free(a);
printf("%s",a); this still prints "gates " why is this happening
even after freeing the memory? should I write
a=NULL;

Please help my simple querries as it will help me a lot.

regards Lee
 
R

Robert Stankowic

Yang Lee said:
Hi All,
I have two char pointers

char *a,*b;
a=(char *)malloc(10);
b=a; /*******/

so both pointers are looking at same mamory location

strcpy(a,"gates");
printf("%s",b);

Now I free pointer b;
free(b);

You don't free _pointer b_, you free _the memory it points_ to.
from this moment the value in b as well as in a is no longer valid and even
the statement

a;
or
b;

invokes undefined behavior [OT](for instance, a segment-descriptor in
certain CPU's may no longer exist and even loading a or b into a
CPU-register may cause a crash)[/OT]
Then will pointer a be in existance or it will be also freed.
or if I free pointer a then will b point to same location.

Also

a=(char *)malloc(10);
strcpy(a,"gates");
free(a);
printf("%s",a); this still prints "gates " why is this happening
even after freeing the memory?

Undefined behavior means everything can happen, your printf in your case
just happens to work by accident, it could as well format your harddisk or
put haircream into your toothpaste :)

should I write

Good idea (IMHO)
Dereferencing a NULL pointer is more likely to crash your application
immidiately, telling you that somethimg is messed up.
And by accident free()ing a NULL pointer does no harm, it's just a no-op.

HTH
Robert
 
J

James Hu

char *a,*b;
a=(char *)malloc(10);
b=a; /*******/
strcpy(a,"gates");
printf("%s",b);

Probably you should use:

printf("%s\n", b);
free(b);

Then will pointer a be in existance or it will be also freed.
or if I free pointer a then will b point to same location.

Since b and a point to the same object prior to the call to free, then
they both point to freed space after the call to free.
Also

a=(char *)malloc(10);
strcpy(a,"gates");
free(a);
printf("%s",a);

See the printf comment above.
this still prints "gates " why is this happening even after freeing
the memory? should I write

a=NULL;

You should never read from or write to an object whose lifetime has
expired. In the case of allocated objects, their lifetime expires after
the call to free. Compare this with automatic objects, whose lifetime
expires when execution reaches the end of the their associated statement
block.

Why you see the "gates" output is not really relevant here, since you
are invoking undefined behavior. One possible answer is that
it is the nature of your C library implementation to not disturb the
contents of freed memory until the memory is allocated and written to
for a different purpose. However, it is a programming error to invoke
undefined behavior.

In almost all cases, a program can not reliably exploit this "do not
disturb" behavior, even if the programmer so wishes. Considering your
example, printf itself may allocate memory and write something for its
own purpose there. Then your snippet above may actually cause the
program to crash.

-- James
 
S

Simon Biber

Yang Lee said:
I have two char pointers

char *a,*b;
a=(char *)malloc(10);
b=a; /*******/

so both pointers are looking at same mamory location

It's rude to point, especially at mammary locations. :)
strcpy(a,"gates");
printf("%s",b);

Now I free pointer b;
free(b);

All good so far. Now the value of both a and b is no longer valid.
Then will pointer a be in existance or it will be also freed.
or if I free pointer a then will b point to same location.

Pointer a and b both store the same memory address. You have
freed the memory at that address, so neither a nor b are now
valid. You must not attempt to free(a) now.
Also

a=(char *)malloc(10);
strcpy(a,"gates");
free(a);
printf("%s",a);

Whoops -- you just used the invalid pointer value in a, so
your program has undefined behaviour. Anything could happen.
this still prints "gates " why is this happening
even after freeing the memory?

Anything could happen, including the possibility that the
memory still contains what was in it before -- for now --
but it may get reallocated or written over, some time in
the future, so you should not rely on this behaviour.
should I write a=NULL;

Only if setting it to a null pointer makes sense in your
particular case. If you have finished with the variable
then there is no need to change its value. If you intend
to re-use the variable then it must be set to a valid
pointer value at some point; if you can be sure that you
will not attempt to read from it before that point, you
can leave it alone until you set it to a correct value.
 
D

Dan Pop

In said:
Probably you should use:

printf("%s\n", b);


Since b and a point to the same object prior to the call to free, then
they both point to freed space after the call to free.

That's hard to tell, considering that their values become indeterminate
after the free() call. There is nothing in the standard preventing the
implementation from turning both of them into null pointers after the
free call, for example.

Dan
 
M

Mac

Hi All,
I have two char pointers

char *a,*b;
a=(char *)malloc(10);
b=a; /*******/

so both pointers are looking at same mamory location

strcpy(a,"gates");
printf("%s",b);

Now I free pointer b;
free(b);

Then will pointer a be in existance or it will be also freed.
or if I free pointer a then will b point to same location.

Pointer a will not be in existence, now. You MUST NOT use it. The same
goes for pointer b. Technically, the pointers still exist, but they no
longer point to memory you can use or inspect.
Also

a=(char *)malloc(10);
strcpy(a,"gates");
free(a);
printf("%s",a); this still prints "gates " why is this happening
even after freeing the memory?

After freeing, you are not supposed to touch or even look at the memory.
In your case, I guess the memory was unchanged, but this is not guaranteed.
should I write
a=NULL;

I think it is a good practice to set a (and b) = NULL, after freeing. This
gives you your best chance of detecting any accidental access. But you
don't have to if you don't want to.
Please help my simple querries as it will help me a lot.

regards Lee

Mac
--
 
C

Christopher Benson-Manica

Dan Pop said:
That's hard to tell, considering that their values become indeterminate
after the free() call. There is nothing in the standard preventing the
implementation from turning both of them into null pointers after the
free call, for example.

Wait, what? Are you saying that

int *a;
a=malloc(sizeof *a); /* check against NULL omitted */
printf( "a=%p\n", (void *)a ); /* let's say it prints 0x012345 */
free( a );
if( a==NULL )
printf( "a is NULL\n" );

that the second printf has a chance in hell of being called?
Undoubtedly I've failed to "engage my brain," but I have no idea what
you're talking about.
 
J

Joona I Palaste

Christopher Benson-Manica said:
Let me guess, UB?

Yes. (Or not necessarily, if a was originally NULL, in which case it
would be a comparison NULL==NULL, which is perfectly safe.)
But free() can't alter its argument anyway (no C function can), so the
if statement is pointless.

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"'It can be easily shown that' means 'I saw a proof of this once (which I didn't
understand) which I can no longer remember'."
- A maths teacher
 
S

Simon Biber

Christopher Benson-Manica said:
^^^^^^^^^^^^^

Let me guess, UB?

But you can avoid that UB:

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

int main(void)
{
int *a;
unsigned char b[sizeof a];
a = malloc(sizeof *a);
if(a != NULL)
{

/* make b hold object representation of valid pointer */
memcpy(b, &a, sizeof a);

/* on call to free, pointer value becomes invalid */
free(a);

/* but I can still compare the object representation */
if(memcmp(&a, b, sizeof a) != 0)
printf("the object representation of a has changed\n");
}
return 0;
}

By the function call semantics of C, I do not believe that
the object representation of a can be changed by the
call to free.
 
D

Dan Pop

In said:
Christopher Benson-Manica said:
^^^^^^^^^^^^^

Let me guess, UB?

But you can avoid that UB:

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

int main(void)
{
int *a;
unsigned char b[sizeof a];
a = malloc(sizeof *a);
if(a != NULL)
{

/* make b hold object representation of valid pointer */
memcpy(b, &a, sizeof a);

/* on call to free, pointer value becomes invalid */
free(a);

/* but I can still compare the object representation */
if(memcmp(&a, b, sizeof a) != 0)
printf("the object representation of a has changed\n");
}
return 0;
}

By the function call semantics of C, I do not believe that
the object representation of a can be changed by the
call to free.

The function call semantics of C are irrelevant to the issue, because it
need not be the function call that alters the object representation of the
pointer. Especially considering that *all* pointers pointing to the freed
block can suffer such an alteration.

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

Once the value has become indeterminate, you can't count on its
representation to be the same as before. The implementation is free to do
anything it wants with it. And you don't need a function call at all to
achieve this:

char *p;
unsigned char repr[sizeof p];
{
char c;
p = &c;
memcpy(repr, &p, sizeof p);
}
/* the result of memcmp(&p, repr, sizeof p) can be anything now */

Dan
 
S

Simon Biber

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

I interpret that phrase quite differently to you. The value is
indeterminate because it is neither a pointer to an object
nor a null pointer. However, I do not see how the representation
could possibly change. The standard says that the value becomes
indeterminate; I agree with that, but I don't see how the
representation could change.

Here is the standard's definition of indeterminate value:
"either an unspecified value or a trap representation"

I fully see why the existing representation of the pointer will
become an unspecified value, or a trap representation; I do not
see how or why the object representation could change.
Once the value has become indeterminate, you can't count on its
representation to be the same as before. The implementation is
free to do anything it wants with it.

I disagree entirely. The implementation has not taken control of
my pointer object itself, only reclaimed the memory that it was
pointing to. The old value of the pointer becomes indeterminate;
either an unspecified value or a trap representation, but the
object representation is not affected.
 
A

Arthur J. O'Dwyer

I interpret that phrase quite differently to you. The value is
indeterminate because it is neither a pointer to an object
nor a null pointer. However, I do not see how the representation
could possibly change. The standard says that the value becomes
indeterminate; I agree with that, but I don't see how the
representation could change.

Nor do I think it can. *However*, you should remember that
there are suddenly many fewer ways to examine that unchanged
value without invoking UB. So, for example,

void *a = malloc(1);
free(a);
assert(a == NULL);
assert(a == &a);

is absolutely allowed to let the first assertion succeed; or
the second; or both at once. So the representation *can*
change, if you do anything dumb like, say, examine the value
of the pointer directly.

OTOH, I think you are correct that

void *a = malloc(1);
unsigned char b[sizeof a];
memcpy(b, &a, sizeof a);
free(a);
assert(memcmp(&a, b, sizeof a) == 0);

is not allowed to do anything unexpected -- by which I probably
mean that the assertion must succeed. *Unless* [lazy weasel
words] the assertion would be allowed to fail even in the absence
of the call to 'free' -- remembering that there can be multiple
equal-valued representations of the same pointer, and myself
being unclear as to whether the implementation be allowed to
switch these representations around arbitrarily.
E.g., could the system store a "last accessed" field inside a
pointer value such that the field would change every time the
pointer's value was loaded or dereferenced? That would rule out
a lot of sneaky mem*() tricks...

-Arthur
 
D

Dan Pop

In said:
I interpret that phrase quite differently to you. The value is
indeterminate because it is neither a pointer to an object
nor a null pointer. However, I do not see how the representation
could possibly change. The standard says that the value becomes
indeterminate; I agree with that, but I don't see how the
representation could change.

The pointer value has changed, right? Where does the standard say that
this change *must* preserve the representation?

Dan
 
J

Joe Wright

Dan said:
The pointer value has changed, right? Where does the standard say that
this change *must* preserve the representation?
I'd be interested in the Standard definition of 'indeterminate'. We
properly pass to free() the address of an allocation made by malloc()
for example. Neither malloc() nor free() know anything about a pointer
object where this address might be or have been stored. free() couldn't
change the object if it wanted to. Neither its value nor its
representation will change. The reason it is indeterminate is that its
value is now invalid, it doesn't point to memory we own. It joins that
large group of 4 billion or so (32-bit) addresses whose validity cannot
be determined.
 
D

Dan Pop

In said:
Dan said:
In said:
[Quoting from C99 6.2.4#2]
The value of a pointer becomes indeterminate when
the object it points to reaches the end of its lifetime.

I interpret that phrase quite differently to you. The value is
indeterminate because it is neither a pointer to an object
nor a null pointer. However, I do not see how the representation
could possibly change. The standard says that the value becomes
indeterminate; I agree with that, but I don't see how the
representation could change.

The pointer value has changed, right? Where does the standard say that
this change *must* preserve the representation?
I'd be interested in the Standard definition of 'indeterminate'.

1 indeterminate value
either an unspecified value or a trap representation
We
properly pass to free() the address of an allocation made by malloc()
for example.

As I have already explained, the semantics of function calls are a
non-issue here: you can achieve the same thing without calling any
function at all.

Dan
 

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


Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top