* Null pointer dereference and side effects
@ 2004-07-18 19:30 Archie Cobbs
2004-07-19 12:37 ` Eljay Love-Jensen
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Archie Cobbs @ 2004-07-18 19:30 UTC (permalink / raw)
To: gcc-help
I have a question about GCC optimizations and null pointers.
Consider this program:
#include <stdlib.h>
int
main(int ac, char **av)
{
int *r1;
int *r2;
r1 = ∾
*r1 = 0;
r2 = (void *)0; /* or (void *)1, etc. */
if (*r1 != *r2)
return 1;
return 1;
}
When run & compiled with gcc -O2 (gcc 3.2.2) it does not segfault.
Clearly this is because the optimizer realizes that *r1 need not be
read in order to know that the function should return 1.
However, in my application I'm relying on the side effects of
dereferencing a null pointer (ie., SEGV signal), so that causes
bugs for me.
I understand that according to the C standard dereferencing a null
pointer results in "undefined" behavior, so gcc is not behaving
incorrectly.
However, is there some way to get the desired semantics? It appears
omitting the -O2 does it, but I'd prefer to not do that.
Thanks,
-Archie
__________________________________________________________________________
Archie Cobbs * CTO, Awarix * http://www.awarix.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-18 19:30 Null pointer dereference and side effects Archie Cobbs
@ 2004-07-19 12:37 ` Eljay Love-Jensen
2004-07-19 14:30 ` Archie Cobbs
2004-07-19 15:28 ` Jeffrey A Law
2004-07-20 9:55 ` Alexandre Oliva
2 siblings, 1 reply; 12+ messages in thread
From: Eljay Love-Jensen @ 2004-07-19 12:37 UTC (permalink / raw)
To: Archie Cobbs, gcc-help
Hi Archie,
Try this...
#include <stdlib.h>
int dummy;
int
main(int ac, char **av)
{
int *r1;
int *r2;
r1 = ∾
*r1 = 0;
r2 = (void *)0; /* or (void *)1, etc. */
dummy = *r1; /* k-boom */
if (*r1 != *r2)
return 1;
return 1;
}
--or this--
#include <stdlib.h>
int
main(int ac, char **av)
{
volatile int *r1;
volatile int *r2;
r1 = ∾
*r1 = 0;
r2 = (void *)0; /* or (void *)1, etc. */
if (*r1 != *r2)
return 1;
return 1;
}
--Eljay
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-19 12:37 ` Eljay Love-Jensen
@ 2004-07-19 14:30 ` Archie Cobbs
0 siblings, 0 replies; 12+ messages in thread
From: Archie Cobbs @ 2004-07-19 14:30 UTC (permalink / raw)
To: Eljay Love-Jensen; +Cc: gcc-help
Eljay Love-Jensen wrote:
> Try this...
>
> #include <stdlib.h>
>
> int dummy;
>
> int
> main(int ac, char **av)
> {
> int *r1;
> int *r2;
>
> r1 = ∾
> *r1 = 0;
> r2 = (void *)0; /* or (void *)1, etc. */
> dummy = *r1; /* k-boom */
> if (*r1 != *r2)
> return 1;
> return 1;
> }
Doesn't segfault..
> --or this--
>
> #include <stdlib.h>
>
> int
> main(int ac, char **av)
> {
> volatile int *r1;
> volatile int *r2;
>
> r1 = ∾
> *r1 = 0;
> r2 = (void *)0; /* or (void *)1, etc. */
> if (*r1 != *r2)
> return 1;
> return 1;
> }
Does segfault..
I should have stated that this C code is being machine generated, so what
I'd really like to know is exactly what to expect from the compiler
so I can adjust the code-generating algorithm appropriately to avoid
such situations. That is, I need to be able to guarantee that null
pointer dereferences don't get optimized away.
One way to do this is using "volatile"...
This all makes me curious about what the compiler's stance is with respect
to side effects. E.g., in the docs for "-fdelete-null-pointer-checks"
it says "The compiler assumes that dereferencing a null pointer would
have halted the program".
But my test program seems to contradict this statement that the compiler
is always aware and respectful of these side effects.
I'm curious if there is some documentation describing exactly what
to expect in this situation.. ?
Thanks,
-Archie
__________________________________________________________________________
Archie Cobbs * CTO, Awarix * http://www.awarix.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-18 19:30 Null pointer dereference and side effects Archie Cobbs
2004-07-19 12:37 ` Eljay Love-Jensen
@ 2004-07-19 15:28 ` Jeffrey A Law
2004-07-19 15:45 ` Archie Cobbs
2004-07-20 9:55 ` Alexandre Oliva
2 siblings, 1 reply; 12+ messages in thread
From: Jeffrey A Law @ 2004-07-19 15:28 UTC (permalink / raw)
To: Archie Cobbs; +Cc: gcc-help
On Sun, 2004-07-18 at 13:27, Archie Cobbs wrote:
> I have a question about GCC optimizations and null pointers.
> Consider this program:
>
> #include <stdlib.h>
>
> int
> main(int ac, char **av)
> {
> int *r1;
> int *r2;
>
> r1 = ∾
> *r1 = 0;
> r2 = (void *)0; /* or (void *)1, etc. */
> if (*r1 != *r2)
> return 1;
> return 1;
> }
>
> When run & compiled with gcc -O2 (gcc 3.2.2) it does not segfault.
> Clearly this is because the optimizer realizes that *r1 need not be
> read in order to know that the function should return 1.
>
> However, in my application I'm relying on the side effects of
> dereferencing a null pointer (ie., SEGV signal), so that causes
> bugs for me.
>
> I understand that according to the C standard dereferencing a null
> pointer results in "undefined" behavior, so gcc is not behaving
> incorrectly.
>
> However, is there some way to get the desired semantics? It appears
> omitting the -O2 does it, but I'd prefer to not do that.
-fno-delete-null-pointer-checks.
jeff
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-19 15:28 ` Jeffrey A Law
@ 2004-07-19 15:45 ` Archie Cobbs
2004-07-19 16:04 ` Eljay Love-Jensen
0 siblings, 1 reply; 12+ messages in thread
From: Archie Cobbs @ 2004-07-19 15:45 UTC (permalink / raw)
To: law; +Cc: gcc-help
Jeffrey A Law wrote:
> > I have a question about GCC optimizations and null pointers.
> > Consider this program:
> >
> > #include <stdlib.h>
> >
> > int
> > main(int ac, char **av)
> > {
> > int *r1;
> > int *r2;
> >
> > r1 = ∾
> > *r1 = 0;
> > r2 = (void *)0; /* or (void *)1, etc. */
> > if (*r1 != *r2)
> > return 1;
> > return 1;
> > }
> >
> > When run & compiled with gcc -O2 (gcc 3.2.2) it does not segfault.
>
> -fno-delete-null-pointer-checks.
Doesn't seem to help in this case (at least not with gcc 3.2.2).
Thanks,
-Archie
__________________________________________________________________________
Archie Cobbs * CTO, Awarix * http://www.awarix.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-19 15:45 ` Archie Cobbs
@ 2004-07-19 16:04 ` Eljay Love-Jensen
2004-07-20 15:30 ` Archie Cobbs
0 siblings, 1 reply; 12+ messages in thread
From: Eljay Love-Jensen @ 2004-07-19 16:04 UTC (permalink / raw)
To: Archie Cobbs, law; +Cc: gcc-help
Hi Archie,
You could try disabling or reviewing the optimizations one at a time, until
you find a likely culprit...
> gcc -fverbose-asm -save-temps -O2 -W -Wall crash.c
> cat crash.s
.file "crash.c"
! GNU C version 3.2 (sparc-sun-solaris2.8)
! compiled by GNU C version 3.2.
! options passed: -fpreprocessed -O2 -W -Wall -fverbose-asm
! options enabled: -fdefer-pop -fomit-frame-pointer
! -foptimize-sibling-calls -fcse-follow-jumps -fcse-skip-blocks
! -fexpensive-optimizations -fthread-jumps -fstrength-reduce -fpeephole
! -fforce-mem -ffunction-cse -fkeep-static-consts -fcaller-saves
! -fpcc-struct-return -fdelayed-branch -fgcse -fgcse-lm -fgcse-sm
! -frerun-cse-after-loop -frerun-loop-opt -fdelete-null-pointer-checks
! -fschedule-insns -fschedule-insns2 -fsched-interblock -fsched-spec
! -fbranch-count-reg -freorder-blocks -fcprop-registers -fcommon
! -fverbose-asm -fgnu-linker -fregmove -foptimize-register-move
! -fargument-alias -fstrict-aliasing -fmerge-constants -fident -fpeephole2
! -fguess-branch-probability -fmath-errno -ftrapping-math
.section ".text"
.align 4
.global main
.type main,#function
.proc 04
main:
!#PROLOGUE# 0
!#PROLOGUE# 1
retl
mov 1, %o0
.LLfe1:
.size main,.LLfe1-main
.ident "GCC: (GNU) 3.2"
HTH,
--Eljay
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-18 19:30 Null pointer dereference and side effects Archie Cobbs
2004-07-19 12:37 ` Eljay Love-Jensen
2004-07-19 15:28 ` Jeffrey A Law
@ 2004-07-20 9:55 ` Alexandre Oliva
2004-07-20 15:15 ` Archie Cobbs
2 siblings, 1 reply; 12+ messages in thread
From: Alexandre Oliva @ 2004-07-20 9:55 UTC (permalink / raw)
To: Archie Cobbs; +Cc: gcc-help
Hi, Archie! Long time...
On Jul 18, 2004, Archie Cobbs <archie@dellroad.org> wrote:
> r2 = (void *)0; /* or (void *)1, etc. */
> if (*r1 != *r2)
> return 1;
> return 1;
> However, in my application I'm relying on the side effects of
> dereferencing a null pointer (ie., SEGV signal), so that causes
> bugs for me.
> I understand that according to the C standard dereferencing a null
> pointer results in "undefined" behavior, so gcc is not behaving
> incorrectly.
> However, is there some way to get the desired semantics?
If you insert an `asm ("" : "+X" (r2));' statement after the
assignment to r2, such that the compiler will no longer have any idea
that r2 is NULL, and won't optimize away the dereference.
--
Alexandre Oliva http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-20 9:55 ` Alexandre Oliva
@ 2004-07-20 15:15 ` Archie Cobbs
2004-07-21 6:44 ` Alexandre Oliva
0 siblings, 1 reply; 12+ messages in thread
From: Archie Cobbs @ 2004-07-20 15:15 UTC (permalink / raw)
To: Alexandre Oliva; +Cc: gcc-help
Alexandre Oliva wrote:
> > However, is there some way to get the desired semantics?
>
> If you insert an `asm ("" : "+X" (r2));' statement after the
> assignment to r2, such that the compiler will no longer have any idea
> that r2 is NULL, and won't optimize away the dereference.
Ah, using asm() is an interesting idea and probably the most
efficient way to do it.. however, your particular suggestion
doesn't seem to work (the program still doesn't segfault)..
$ cat > xx.c
#include <stdlib.h>
int
main(int ac, char **av)
{
int *r1;
int *r2;
r1 = ∾
*r1 = 0;
r2 = (void *)0;
asm ("" : "+X" (r2));
if (*r1 != *r2)
return 1;
return 1;
}
^D
$ gcc -o xx -Wall -O2 xx.c
$ ./xx
$
It appears gcc is completely ignoring the possibility of
"side effects" when it optimizes away the comparison.
-Archie
__________________________________________________________________________
Archie Cobbs * CTO, Awarix * http://www.awarix.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-19 16:04 ` Eljay Love-Jensen
@ 2004-07-20 15:30 ` Archie Cobbs
0 siblings, 0 replies; 12+ messages in thread
From: Archie Cobbs @ 2004-07-20 15:30 UTC (permalink / raw)
To: Eljay Love-Jensen; +Cc: law, gcc-help
Eljay Love-Jensen wrote:
> You could try disabling or reviewing the optimizations one at a time, until
> you find a likely culprit...
Interestingly, I can turn all the "-f" flags off and it still doesn't
segfault. However, if I omit the "-O2" but turn all the "-f" flags on,
it always does segfault.
So the offending optimization appears to only depend on "-O2" and
not on any of the flags implied by -O2:
# GNU C version 3.2.2 20030222 (Red Hat Linux 3.2.2-5) (i386-redhat-linux)
# compiled by GNU C version 3.2.2 20030222 (Red Hat Linux 3.2.2-5).
# options passed: -fpreprocessed -O2 -Wall -fverbose-asm
# options enabled: -fdefer-pop -foptimize-sibling-calls -fcse-follow-jumps
# -fcse-skip-blocks -fexpensive-optimizations -fthread-jumps
# -fstrength-reduce -fpeephole -fforce-mem -ffunction-cse
# -fkeep-static-consts -fcaller-saves -fpcc-struct-return -fgcse -fgcse-lm
# -fgcse-sm -frerun-cse-after-loop -frerun-loop-opt
# -fdelete-null-pointer-checks -fschedule-insns2 -fsched-interblock
# -fsched-spec -fbranch-count-reg -freorder-blocks -fcprop-registers
# -fcommon -fverbose-asm -fgnu-linker -fregmove -foptimize-register-move
# -fargument-alias -fstrict-aliasing -fmerge-constants -fident -fpeephole2
# -fguess-branch-probability -fmath-errno -ftrapping-math -m80387
# -mhard-float -mno-soft-float -mieee-fp -mfp-ret-in-387 -mcpu=i386
# -march=i386
Thanks,
-Archie
__________________________________________________________________________
Archie Cobbs * CTO, Awarix * http://www.awarix.com
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-20 15:15 ` Archie Cobbs
@ 2004-07-21 6:44 ` Alexandre Oliva
2004-07-21 11:33 ` Eljay Love-Jensen
0 siblings, 1 reply; 12+ messages in thread
From: Alexandre Oliva @ 2004-07-21 6:44 UTC (permalink / raw)
To: Archie Cobbs; +Cc: gcc-help
On Jul 20, 2004, Archie Cobbs <archie@dellroad.org> wrote:
> It appears gcc is completely ignoring the possibility of
> "side effects" when it optimizes away the comparison.
Oh, rats. That's because the reasoning about dereferencing NULL
invoking undefined behavior still applies. Since both arms of the if
return the same value, the compare is optimized away, and the
dereference of the pointer can be removed because, if it was NULL or
any other bad pointer, it would invoke undefined behavior, and
otherwise, the dereference would be safe and unused.
I think you really need to make the pointer volatile to prevent the
dereference from being optimized out.
--
Alexandre Oliva http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-21 6:44 ` Alexandre Oliva
@ 2004-07-21 11:33 ` Eljay Love-Jensen
2004-07-22 20:24 ` Alexandre Oliva
0 siblings, 1 reply; 12+ messages in thread
From: Eljay Love-Jensen @ 2004-07-21 11:33 UTC (permalink / raw)
To: Alexandre Oliva, Archie Cobbs; +Cc: gcc-help
Hi Alexandre & Archie,
>I think you really need to make the pointer volatile to prevent the
dereference from being optimized out.
Making a pointer volatile:
int * volatile p;
Making what the pointer points to volatile:
volatile int * p;
I presume the former is the prerequisite magic voodoo, and that between the
two they may optimize differently. (I haven't actually tested the
theory. Just wanted to point it out for Archie.)
Sincerely,
--Eljay
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Null pointer dereference and side effects
2004-07-21 11:33 ` Eljay Love-Jensen
@ 2004-07-22 20:24 ` Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2004-07-22 20:24 UTC (permalink / raw)
To: Eljay Love-Jensen; +Cc: Archie Cobbs, gcc-help
On Jul 21, 2004, Eljay Love-Jensen <eljay@adobe.com> wrote:
> Making what the pointer points to volatile:
> volatile int * p;
Sorry, this is what I meant. Although making the pointer volatile
would actually force the memory location holding the pointer to be
loaded, it wouldn't force the memory location it points to to remain.
--
Alexandre Oliva http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2004-07-22 20:24 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-18 19:30 Null pointer dereference and side effects Archie Cobbs
2004-07-19 12:37 ` Eljay Love-Jensen
2004-07-19 14:30 ` Archie Cobbs
2004-07-19 15:28 ` Jeffrey A Law
2004-07-19 15:45 ` Archie Cobbs
2004-07-19 16:04 ` Eljay Love-Jensen
2004-07-20 15:30 ` Archie Cobbs
2004-07-20 9:55 ` Alexandre Oliva
2004-07-20 15:15 ` Archie Cobbs
2004-07-21 6:44 ` Alexandre Oliva
2004-07-21 11:33 ` Eljay Love-Jensen
2004-07-22 20:24 ` Alexandre Oliva
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).