public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* 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 = &ac;
	    *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 = &ac;
	    *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 = &ac;
	    *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 = &ac;
> 	    *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 = &ac;
> 	    *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 = &ac;
> 	    *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 = &ac;
> > 	    *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 = &ac;
	    *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).