Destroying All Nodes is a Linked List 
Author Message
 Destroying All Nodes is a Linked List

Quote:

> When the statement:

> free (*Head);

> is used is the pointer *Head set to NULL or must that be done by the
> programmer?  

After a pointer is free()'d, its value is indeterminate. That is, you may
not test, retrieve, compare, or access it in any way. If you need *Head to
be NULL, assign it.

--
Attempting to write in a hybrid which can be compiled by either a C compiler
or a C++ compiler produces a compromise language which combines the drawbacks
of both with the advantages of neither.



Sun, 30 Jul 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List

Derek...

I suspect that you could have figured this one out for yourself!

You are passing the value of a pointer to the storage you want freed!

free() has no way to set the pointer to NULL because it hasn't a clue as to
where the pointer might be -- all it has is the value.

Morris Dovey

Des Moines, Iowa, USA



Mon, 31 Jul 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List

Quote:

> When the statement:

> free (*Head);

> is used is the pointer *Head set to NULL or must that be done by the
> programmer?

You have to do it yourself.

Think about it. If free() could set a pointer to NULL then
you would pass a pointer to the pointer. ie. free(&p);

You don't pass a pointer, so free() can't possibly set it to NULL.

This is in the FAQ:

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

--
<\___/>      | Politicians are the same all over.  They promise to build
/ O O \      | a bridge even where there is no river.
\_____/ FTB. |        -- Nikita Khrushchev



Mon, 31 Jul 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List


Quote:

>Derek...

>I suspect that you could have figured this one out for yourself!

>You are passing the value of a pointer to the storage you want freed!

>free() has no way to set the pointer to NULL because it hasn't a clue as to
>where the pointer might be -- all it has is the value.

As has been discussed on this newsgroup at length in the past, free()
*could* set the pointer (and indeed, all pointers which point to the
same thing) to NULL (or any other value) but there's no way for your
program to find out whether it did or not.  The value of the pointer
after the call to free() is indeterminate so you aren't even allowed
to examine it.

If you require it to be a null pointer after the free() you must do
an explicit assignment yourself.

John
--
John Winters.  Wallingford, Oxon, England.

The Linux Emporium - a source for Linux CDs in the UK
See <http://www.polo.demon.co.uk/emporium.html>



Tue, 01 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List



Quote:


>>Derek...

>>I suspect that you could have figured this one out for yourself!

>>You are passing the value of a pointer to the storage you want freed!

>>free() has no way to set the pointer to NULL because it hasn't a clue as to
>>where the pointer might be -- all it has is the value.

>As has been discussed on this newsgroup at length in the past, free()
>*could* set the pointer (and indeed, all pointers which point to the
>same thing) to NULL (or any other value) but there's no way for your
>program to find out whether it did or not.

What the standard says is that you can't access it as a pointer (the value
is indeterminate when accessed as a pointer). However I believe that the
following is a strictly conforming program is strictly conforming:

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

int main(void)
{
    void *p1;
    unsigned char a[sizeof p1];

    p1 = malloc(1);

    memcpy(a, &p1, sizeof p1);

    free(p1);

    if (memcmp(a, &p1, sizeof p1) != 0)
        printf("p1 changed\n");

    return 0;

Quote:
}

free() is defined using the normal call-by-value function semantics so
it can't change its argument. Therefore if this code outputs ``p1 changed''
the implementation is not conforming.

The fact that the bits in the p1 object haven't changed doesn't mean that
you can access its value as a pointer. On a (proper) segmented archetecture
p1 as a pointer might refer to a segment which no longer exists after the
call to free so just looking at its value (as a pointer) may cause a trap.
That is why the *pointer* value (and indeed the value of any pointer that
pointed at the freed object) is made indeterminate by the standard after
the call to free.

Quote:
>If you require it to be a null pointer after the free() you must do
>an explicit assignment yourself.

Right.

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


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



Tue, 01 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List


[snip]

Quote:
>free() is defined using the normal call-by-value function semantics so
>it can't change its argument. Therefore if this code outputs ``p1 changed''
>the implementation is not conforming.

I'm not convinced that just the fact of call-by-value precludes the
possibility of free() changing the value of the pointer.  It's possible
that the value provides sufficient information for all pointers to
the relevant data item to be traced.


for an explanation of how even *user* code can do this.  free(), being
part of the implementation potentially has even more facilities at its
disposal.

John
--
John Winters.  Wallingford, Oxon, England.

The Linux Emporium - a source for Linux CDs in the UK
See <http://www.polo.demon.co.uk/emporium.html>



Tue, 01 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List



Quote:


>[snip]
>>free() is defined using the normal call-by-value function semantics so
>>it can't change its argument. Therefore if this code outputs ``p1 changed''
>>the implementation is not conforming.

>I'm not convinced that just the fact of call-by-value precludes the
>possibility of free() changing the value of the pointer.  It's possible
>that the value provides sufficient information for all pointers to
>the relevant data item to be traced.

However changing the contents of the pointer object would be a side-effect
not documented by the standard hence one that a strictly conforming program
can rely on not happening.

Quote:

>for an explanation of how even *user* code can do this.

OK, I'll take a look but I suspect that either

1. what the code does cannot be done in a strictly conforming program, or

2. the code performs an action that creates a suitable explicit side-effect
   according to the language definition.

There's nothing in the definition of free that permits it to affect any
object accessible to the program other than the one pointed to by its
argument.

Quote:
> free(), being
>part of the implementation potentially has even more facilities at its
>disposal.

It can perform whatever magic it likes but the end result is constrained
by the behaviour that is required by the standard, just like any other
standard library function. If free() can alter its argument what is to stop
any other standard library function doing so?

The key phrase here is in 7.10.3: "The value of a pointer that refers
to freed space is indeterminate".

What it does *not* say is that the contents of a pointer object become
indeterminate (or are in any way modified) when the object pointed to is
freed. In fact it can't say that because objects themselves in C don't have
an inherent type, they are simply a contiguous sequence of bytes. In addition
3.14 says "When referenced, an object may be interpreted as having a
particular type: see 6.2.2.1". What that means is that the contents of an
object is simply interpreted using the type of the lvalue it happens to be
accessed through at that instant. So free() cannot, for example, search
through a program's data space looking for pointers to the freed object and
change them, because it can't tell whether the ``pointer'' object contents
will be interpreted as a pointer or not. That is determined purely by the way
the program accesses the object.

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


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



Tue, 01 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List



Quote:
>That is why the *pointer* value (and indeed the value of any pointer that
>pointed at the freed object) is made indeterminate by the standard after
>the call to free.

Except if the pointer was NULL to begin with.

Quote:
>>If you require it to be a null pointer after the free() you must do
>>an explicit assignment yourself.

>Right.

--

http://www.cs.wustl.edu/~jxh/        Washington University in Saint Louis
Quote:
>>>>>>>>>>>>> I use *SpamBeGone* <URL:http://www.internz.com/SpamBeGone/>



Wed, 02 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List


Quote:





>>[snip]
>>>free() is defined using the normal call-by-value function semantics so
>>>it can't change its argument. Therefore if this code outputs ``p1 changed''
>>>the implementation is not conforming.

>>I'm not convinced that just the fact of call-by-value precludes the
>>possibility of free() changing the value of the pointer.  It's possible
>>that the value provides sufficient information for all pointers to
>>the relevant data item to be traced.

>However changing the contents of the pointer object would be a side-effect
>not documented by the standard hence one that a strictly conforming program
>can rely on not happening.

IIRC, the last time this was discussed, Doug Gwyn stepped in and
explained that the standard should not be interpreted as allowing
free() to change the contents of the pointer. Furthermore, that any
implementation that does this needs to be fixed.

A program can't access the pointer value directly, like this:

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

int main(void)
{
        void *p = malloc(42), *q = p;

        free(p);
        if (p == q) printf("Unchanged\n");
        else printf("Changed\n");
        return 0;

Quote:
}

But it can like this:

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

int main(void)
{
        void *p = malloc(42);
        unsigned char r[sizeof p];
        unsigned char *s = (unsigned char *)&p;
        int i;

        for (i = 0; i < sizeof p; i++)
                r[i] = s[i];
        free(p);
        for (i = 0; i < sizeof p; i++)
                if (r[i] != s[i]) break;
        if (i == sizeof p) printf("Unchanged\n");
        else printf("Changed\n");
        return 0;

Quote:
}

The first program can print "Hello World". The second program must
print "Unchanged".

Ulric
--
Style is always a matter of style.



Wed, 02 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List


Quote:

>IIRC, the last time this was discussed, Doug Gwyn stepped in and
>explained that the standard should not be interpreted as allowing
>free() to change the contents of the pointer. Furthermore, that any
>implementation that does this needs to be fixed.

>A program can't access the pointer value directly, like this:

Really?  You are referring the the following program.
Why not? There is something wrong here.

First program:

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

>int main(void)
>{
>        void *p = malloc(42), *q = p;

>        free(p);
>        if (p == q) printf("Unchanged\n");
>        else printf("Changed\n");
>        return 0;
>}

.....snip....

Quote:
>The first program can print "Hello World". The second program must
>print "Unchanged".

How is it possible that this program will print
"Hello World"?

Al Bowers                                
Tampa, FL

http://www.gate.net/~abowers/index.html



Thu, 03 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List

Quote:



> >IIRC, the last time this was discussed, Doug Gwyn stepped in and
> >explained that the standard should not be interpreted as allowing
> >free() to change the contents of the pointer. Furthermore, that any
> >implementation that does this needs to be fixed.

> >A program can't access the pointer value directly, like this:
> Really?  You are referring the the following program.
> Why not? There is something wrong here.

> First program:
> >#include <stdio.h>
> >#include <stdlib.h>

> >int main(void)
> >{
> >        void *p = malloc(42), *q = p;

> >        free(p);
> >        if (p == q) printf("Unchanged\n");
> >        else printf("Changed\n");
> >        return 0;
> >}
> .....snip....

> >The first program can print "Hello World". The second program must
> >print "Unchanged".
> How is it possible that this program will print
> "Hello World"?

  Hm-m...
Comparing two pointers, when one of them is invalidated by free(),
spells undefined behaviour. Though I'll be sincerely surprised if
the program in question will output "Hello, World", it is permitted
by the Standard, isn't it?
  My newsserver doesn't show Ulric's post yet, but I guess his
second example deals with accessing invalid pointer's bit pattern as
unsigned char array? That is really re-creation of a not-so-forgotten
thread. Do we need to continue this merry-go-round? It was long long:)

        Regards,
                Alex Krol



Thu, 03 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List

Quote:


> > How is it possible that this program will print
> > "Hello World"?

> Comparing two pointers, when one of them is invalidated by free(),
> spells undefined behaviour.

Right.

Quote:
> Though I'll be sincerely surprised if the program in question will output
> "Hello, World", it is permitted by the Standard, isn't it?

It is, indeed. Undefined behavior means absolutely anything and everything
can happen. The canonical c.l.c example is hard drive formatting. :)

Quote:
>   My newsserver doesn't show Ulric's post yet, but I guess his
> second example deals with accessing invalid pointer's bit pattern as
> unsigned char array?

Using memcpy() and memcmp(), yes.

--
Attempting to write in a hybrid which can be compiled by either a C compiler
or a C++ compiler produces a compromise language which combines the drawbacks
of both with the advantages of neither.



Thu, 03 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List


Quote:



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

>>int main(void)
>>{
>>        void *p = malloc(42), *q = p;

>>        free(p);
>>        if (p == q) printf("Unchanged\n");
>>        else printf("Changed\n");
>>        return 0;
>>}

>How is it possible that this program will print
>"Hello World"?

After the call to free(), the value of p is indeterminate. Use of
this value (even without dereferencing it) results in undefined
behaviour.

Ulric
--
You have committed Hungarian Heresey. You will be assimonylated.



Thu, 03 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List


Quote:

>  My newsserver doesn't show Ulric's post yet, but I guess his
>second example deals with accessing invalid pointer's bit pattern as
>unsigned char array? That is really re-creation of a not-so-forgotten
>thread. Do we need to continue this merry-go-round? It was long long:)

Yep, so I thought it would help to post a spoiler right away. There
is no need to go through it the hard way again.

Ulric
--
You have committed Hungarian Heresey. You will be assimonylated.



Thu, 03 Aug 2000 03:00:00 GMT  
 Destroying All Nodes is a Linked List


Quote:





>>>Derek...

>>>I suspect that you could have figured this one out for yourself!

>>>You are passing the value of a pointer to the storage you want freed!

>>>free() has no way to set the pointer to NULL because it hasn't a clue as to
>>>where the pointer might be -- all it has is the value.

>>As has been discussed on this newsgroup at length in the past, free()
>>*could* set the pointer (and indeed, all pointers which point to the
>>same thing) to NULL (or any other value) but there's no way for your
>>program to find out whether it did or not.

>What the standard says is that you can't access it as a pointer (the value
>is indeterminate when accessed as a pointer). However I believe that the
>following is a strictly conforming program is strictly conforming:

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

>int main(void)
>{
>    void *p1;
>    unsigned char a[sizeof p1];

>    p1 = malloc(1);

>    memcpy(a, &p1, sizeof p1);

>    free(p1);

>    if (memcmp(a, &p1, sizeof p1) != 0)
>        printf("p1 changed\n");

>    return 0;
>}

>free() is defined using the normal call-by-value function semantics so
>it can't change its argument. Therefore if this code outputs ``p1 changed''
>the implementation is not conforming.

>The fact that the bits in the p1 object haven't changed doesn't mean that
>you can access its value as a pointer. On a (proper) segmented archetecture
>p1 as a pointer might refer to a segment which no longer exists after the
>call to free so just looking at its value (as a pointer) may cause a trap.
>That is why the *pointer* value (and indeed the value of any pointer that
>pointed at the freed object) is made indeterminate by the standard after
>the call to free.

True, but there's still no way to tell if it has been changed to a
null pointer.  While the bit pattern can't change, the interpretation
can and nothing I can find in the standard requires all null pointers
to have the same representation.  It could be that before the free(),
a == 0 would be 0 and after it would be 1 even if the bit pattern
stored in a did not change.
--
Michael M Rubenstein


Thu, 03 Aug 2000 03:00:00 GMT  
 
 [ 16 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Destroying All Nodes in a Linked List

2. nodes linked listed and such

3. 2 nodes end up in a cycle in a single linked list

4. newbie question: removal of node in linked list

5. How to find a node in link list

6. Realloc()ing data of a node from a linked list

7. why malloc for a new node in linked list

8. Removing node from linked list

9. Removing a NODE for good (double linked lists)

10. deleting a previous node in a singly linked list

11. Question about swapping nodes in a doubly linked list

12. Deleting a node in a linked list

 

 
Powered by phpBB® Forum Software