Author |
Message |
firewin #1 / 16
|
 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 |
|
 |
Morris Dove #2 / 16
|
 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 |
|
 |
Colin Doole #3 / 16
|
 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 |
|
 |
John Winte #4 / 16
|
 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 |
|
 |
Lawrence Kir #5 / 16
|
 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 |
|
 |
John Winte #6 / 16
|
 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 |
|
 |
Lawrence Kir #7 / 16
|
 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 |
|
 |
James #8 / 16
|
 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 |
|
 |
Ulric Erikss #9 / 16
|
 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 |
|
 |
Al Bowe #10 / 16
|
 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 |
|
 |
Alex Kro #11 / 16
|
 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 |
|
 |
firewin #12 / 16
|
 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 |
|
 |
Ulric Erikss #13 / 16
|
 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 |
|
 |
Ulric Erikss #14 / 16
|
 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 |
|
 |
Michael Rubenste #15 / 16
|
 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 |
|
|