void pointer cast segfaults

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andreas Schmidt

    void pointer cast segfaults

    I am trying to understand the behavior of void pointers. Can someone
    explain to me why I get a segfault for the following program?

    #include <stdio.h>

    void* plusone(void* i){
    int* arg = (int*)i;
    int result = (*arg + 1);
    return (void*)result;
    }
    int main(){
    void* w1 = (void*)10;
    void* result = plusone(w1);
    printf("%d", *(int*)result);
    }

    According to gdb, the cast in the first line of plusone gives the segfault.
    Why??

    Markus

    P.S.: I compiled with gcc 3.2.2
  • Peter Nilsson

    #2
    Re: void pointer cast segfaults

    Andreas Schmidt wrote:[color=blue]
    > I am trying to understand the behavior of void pointers.[/color]

    You're really trying to explain why accessing random addresses
    causes your machine to segfault.
    [color=blue]
    > Can someone explain to me why I get a segfault for the
    > following program?
    >
    > #include <stdio.h>
    >
    > void* plusone(void* i){
    > int* arg = (int*)i;[/color]

    The (int *) cast is unnecessary. But the conversion may fail if the
    resulting pointer is not suitably aligned for an int.
    [color=blue]
    > int result = (*arg + 1);[/color]

    You're trying to get an int value from memory you probably don't own.
    [color=blue]
    > return (void*)result;[/color]

    The conversion of an int to a void * is implementation defined.
    [color=blue]
    > }
    > int main(){
    > void* w1 = (void*)10;[/color]

    Again the conversion is implementation defined. It is utterly useless
    in portable programming because you have _no idea_ what 10 will
    represent when converted to a pointer.
    [color=blue]
    > void* result = plusone(w1);
    > printf("%d", *(int*)result);[/color]

    Again you try and grab an int value from memory you don't own.

    Also, without a trailing \n, you have no guarantee of output anyway.
    [color=blue]
    > }
    >
    > According to gdb, the cast in the first line of plusone gives
    > the segfault.
    > Why??[/color]

    What are you actually trying to do? If it is implementation specific,
    then ask in an implementation specific newsgroup.

    If you're just trying things, then realise that C is probably the
    _worst_ language to learn through pure experimentation .

    --
    Peter

    Comment

    • Old Wolf

      #3
      Re: void pointer cast segfaults

      Andreas Schmidt wrote:[color=blue]
      > Can someone explain to me why I get a segfault for the
      > following program?
      >
      > According to gdb, the cast in the first line of plusone
      > gives the segfault. Why??[/color]
      [color=blue]
      > #include <stdio.h>
      >
      > int main(){
      > void* w1 = (void*)10;[/color]

      In general, this is illegal: you cannot cast an int to a pointer.
      In your case, you will probably end up with a pointer to address
      number 10 on your PC.
      [color=blue]
      > void* result = plusone(w1);[/color]

      Now let's look at plusone() (I have rearranged your post a little):
      [color=blue]
      > void* plusone(void* i){
      > int* arg = (int*)i;[/color]

      You are casting the address 10 to be a pointer to int. This
      may also be illegal (for example, on some systems, ints can
      only reside at addresses that are a multiple of 4).
      [color=blue]
      > int result = (*arg + 1);[/color]

      This is definitely a problem: you are retrieving an int from
      address 10. On a system like Windows XP or Unix or Linux,
      you will get a segmentation fault because your program
      is not allowed to access address 10 (it can only access
      addresses in its own address space).
      [color=blue]
      > return (void*)result;[/color]

      Casting an int to a pointer -- illegal, as I mentioned before.
      [color=blue]
      > }[/color]

      Now we're back to main():
      [color=blue]
      > printf("%d", *(int*)result);[/color]

      Again, dereferencing a pointer to an address you probably
      don't own, this will probably give you a segmentation fault.
      [color=blue]
      > }
      >
      >
      > I am trying to understand the behavior of void pointers.
      >[/color]

      Your code really has nothing to do with void pointers as such,
      you could have used int pointers or char pointers and
      got the same problems. Generally, you cannot convert between
      ints and pointers in this way.

      A "void pointer" (or more accurately, a pointer-to-void) is
      a pointer where you don't know the type of what it's pointing
      to. You can convert other POINTERS into void pointers, and
      convert them back again. You can't convert ints etc. into
      void pointers.

      Here's an example of what you can do:

      void plusone(void *ptr)
      {
      *(int *)ptr += 1;
      }

      int main()
      {
      int x = 5;
      void *ptr = &x;
      plusone(ptr);
      printf("%d\n", x);
      }

      Comment

      • Andreas Schmidt

        #4
        Re: void pointer cast segfaults

        Peter Nilsson wrote:
        [color=blue]
        > Andreas Schmidt wrote:[color=green]
        >> I am trying to understand the behavior of void pointers.[/color][/color]
        [color=blue]
        > The conversion of an int to a void * is implementation defined.
        >[color=green]
        >> }
        >> int main(){
        >> void* w1 = (void*)10;[/color]
        >
        > Again the conversion is implementation defined. It is utterly useless
        > in portable programming because you have _no idea_ what 10 will
        > represent when converted to a pointer.[/color]

        I don't think it's utterly useless. The following program works fine:

        #include <stdio.h>
        int main(){
        void* i = (void*)10;
        printf("%d\n", (int*)i);
        return 0;
        }

        What do you mean by "implementa tion specific"? Are you saying I'm just
        lucky that it compiles and runs, but it depends on the implementation of
        the compiler?




        Comment

        • Andreas Schmidt

          #5
          Re: void pointer cast segfaults

          Andreas Schmidt wrote:
          [color=blue]
          > The following program works fine:
          >
          > #include <stdio.h>
          > int main(){
          > void* i = (void*)10;
          > printf("%d\n", (int*)i);
          > return 0;
          > }[/color]

          OK, now I understand I am really just printing the pointer address here...

          A.

          Comment

          • Keith Thompson

            #6
            Re: void pointer cast segfaults

            Andreas Schmidt <schmidt.2004@g mx.de> writes:[color=blue]
            > Andreas Schmidt wrote:
            >[color=green]
            >> The following program works fine:
            >>
            >> #include <stdio.h>
            >> int main(){
            >> void* i = (void*)10;
            >> printf("%d\n", (int*)i);
            >> return 0;
            >> }[/color]
            >
            > OK, now I understand I am really just printing the pointer address here...[/color]

            You *might* be printing the address. By using an int* argument with a
            "%d" format, you're invoking undefind behavior. (In particular, it's
            not uncommon for int and int* to have different sizes.)

            --
            Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
            San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
            We must do something. This is something. Therefore, we must do this.

            Comment

            • Emmanuel Delahaye

              #7
              Re: void pointer cast segfaults

              Andreas Schmidt wrote on 05/05/05 :
              #include <stdio.h>

              void *plusone (void *i)
              {
              /* -ed- the value of i is unspecified */

              int *arg = (int *) i;
              /* -ed- the value of arg is unspecified */

              int result = (*arg + 1);
              /* -ed- the value of *arg is undefined */

              return (void *) result;
              /* -ed-
              * I'm lost.
              * Why in the world are you frankensteining your code like that ?
              * Cast is evil, didn't your mom told you that before ?
              */
              }

              int main (void)
              {
              /* -ed-
              * the result of the conversion of an integer to a pointer constant
              * is implementation defined. On my platform, the result is
              unspecified.
              *
              * Using the value of w1 invokes an undefined behaviour.
              */
              void *w1 = (void *) 10;

              void *result = plusone (w1);
              printf ("%d", *(int *) result);
              }

              --
              Emmanuel
              The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
              The C-library: http://www.dinkumware.com/refxc.html

              ..sig under repair

              Comment

              • Cian

                #8
                Re: void pointer cast segfaults


                "Andreas Schmidt" <schmidt.2004@g mx.de> wrote in message
                news:3dti3aF4jq 9U1@individual. net...[color=blue]
                > I am trying to understand the behavior of void pointers. Can someone
                > explain to me why I get a segfault for the following program?
                >
                > #include <stdio.h>
                >
                > void* plusone(void* i){
                > int* arg = (int*)i;
                > int result = (*arg + 1);
                > return (void*)result;[/color]
                change this to: return (void*)&result;
                return the address of result (cast to a void *) [or a pointer to result]
                [color=blue]
                > }
                > int main(){
                > void* w1 = (void*)10;[/color]
                change this to: void* w1 = (void*)&10;

                w1 is assigned the address of 10 (cast to a void *) [or a pointer to
                address][color=blue]
                > void* result = plusone(w1);
                > printf("%d", *(int*)result);
                > }
                >[/color]


                Cian


                Comment

                • Lawrence Kirby

                  #9
                  Re: void pointer cast segfaults

                  On Thu, 05 May 2005 09:47:49 +0100, Cian wrote:
                  [color=blue]
                  >
                  > "Andreas Schmidt" <schmidt.2004@g mx.de> wrote in message
                  > news:3dti3aF4jq 9U1@individual. net...[color=green]
                  >> I am trying to understand the behavior of void pointers. Can someone
                  >> explain to me why I get a segfault for the following program?
                  >>
                  >> #include <stdio.h>
                  >>
                  >> void* plusone(void* i){
                  >> int* arg = (int*)i;
                  >> int result = (*arg + 1);
                  >> return (void*)result;[/color]
                  > change this to: return (void*)&result;
                  > return the address of result (cast to a void *) [or a pointer to result]
                  >[color=green]
                  >> }
                  >> int main(){
                  >> void* w1 = (void*)10;[/color]
                  > change this to: void* w1 = (void*)&10;[/color]

                  10 isn't an lvalue, it is not a valid operand for &. You could change it
                  to

                  int value = 10;
                  void *w1 = &value;
                  [color=blue]
                  > w1 is assigned the address of 10 (cast to a void *) [or a pointer to
                  > address][/color]

                  Since 10 is not an object or function it has no address.

                  Lawrence

                  Comment

                  • Jim Hunter

                    #10
                    Re: void pointer cast segfaults

                    "Cian" <cian1810@REMOV EfastmailTHIS.f m> writes:
                    [color=blue][color=green]
                    > > void* plusone(void* i){
                    > > int* arg = (int*)i;
                    > > int result = (*arg + 1);
                    > > return (void*)result;[/color]
                    > change this to: return (void*)&result;
                    > return the address of result (cast to a void *) [or a pointer to result][/color]

                    Not a good idea to return a pointer to a local variable.

                    Jim

                    --
                    I was born not knowing and have had only a little time to change
                    that here and there. -- Richard Feynman

                    Comment

                    • Keith Thompson

                      #11
                      Re: void pointer cast segfaults

                      "Old Wolf" <oldwolf@inspir e.net.nz> writes:[color=blue]
                      > Andreas Schmidt wrote:[color=green]
                      >> Can someone explain to me why I get a segfault for the
                      >> following program?
                      >>
                      >> According to gdb, the cast in the first line of plusone
                      >> gives the segfault. Why??[/color]
                      >[color=green]
                      >> #include <stdio.h>
                      >>
                      >> int main(){
                      >> void* w1 = (void*)10;[/color]
                      >
                      > In general, this is illegal: you cannot cast an int to a pointer.[/color]

                      Not quite. C99 6.3.2.3p5 says:

                      An integer may be converted to any pointer type. Except as
                      previously specified, the result is implementation-defined, might
                      not be correctly aligned, might not point to an entity of the
                      referenced type, and might be a trap representation.

                      (The "previously specified" refers to null pointer constants.)
                      [color=blue]
                      > In your case, you will probably end up with a pointer to address
                      > number 10 on your PC.[/color]

                      Probably. A footnote says:

                      The mapping functions for converting a pointer to an integer or an
                      integer to a pointer are intended to be consistent with the
                      addressing structure of the execution environment.

                      Of course, the result is vanishingly unlikely to be useful.

                      --
                      Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                      San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
                      We must do something. This is something. Therefore, we must do this.

                      Comment

                      • Barry Schwarz

                        #12
                        Re: void pointer cast segfaults

                        On Thu, 05 May 2005 06:25:39 GMT, Keith Thompson <kst-u@mib.org>
                        wrote:
                        [color=blue]
                        >Andreas Schmidt <schmidt.2004@g mx.de> writes:[color=green]
                        >> Andreas Schmidt wrote:
                        >>[color=darkred]
                        >>> The following program works fine:
                        >>>
                        >>> #include <stdio.h>
                        >>> int main(){
                        >>> void* i = (void*)10;
                        >>> printf("%d\n", (int*)i);
                        >>> return 0;
                        >>> }[/color]
                        >>
                        >> OK, now I understand I am really just printing the pointer address here...[/color]
                        >
                        >You *might* be printing the address. By using an int* argument with a
                        >"%d" format, you're invoking undefind behavior. (In particular, it's
                        >not uncommon for int and int* to have different sizes.)[/color]

                        It also invokes undefined behavior in those cases where the value 10
                        does not represent the suitably aligned value for the address of an
                        int.


                        <<Remove the del for email>>

                        Comment

                        • Christian Bau

                          #13
                          Re: void pointer cast segfaults

                          In article <3dtkg8F4mldU1@ individual.net> ,
                          Andreas Schmidt <schmidt.2004@g mx.de> wrote:
                          [color=blue]
                          > Peter Nilsson wrote:
                          >[color=green]
                          > > Andreas Schmidt wrote:[color=darkred]
                          > >> I am trying to understand the behavior of void pointers.[/color][/color]
                          >[color=green]
                          > > The conversion of an int to a void * is implementation defined.
                          > >[color=darkred]
                          > >> }
                          > >> int main(){
                          > >> void* w1 = (void*)10;[/color]
                          > >
                          > > Again the conversion is implementation defined. It is utterly useless
                          > > in portable programming because you have _no idea_ what 10 will
                          > > represent when converted to a pointer.[/color]
                          >
                          > I don't think it's utterly useless. The following program works fine:
                          >
                          > #include <stdio.h>
                          > int main(){
                          > void* i = (void*)10;
                          > printf("%d\n", (int*)i);
                          > return 0;
                          > }
                          >
                          > What do you mean by "implementa tion specific"? Are you saying I'm just
                          > lucky that it compiles and runs, but it depends on the implementation of
                          > the compiler?[/color]

                          No, you are extremely unlucky.

                          Luck is when a crappy program crashes on you, giving you the chance the
                          fix it and may be to learn something.

                          Comment

                          Working...