Pointing past valid memory

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • jois.de.vivre@gmail.com

    #1

    Pointing past valid memory

    Hello, I was wondering if the following code was ok:

    // ----------- start code

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

    int main(int argc, char** argv)
    {
    char buf[10];
    memset(buf, 'a', sizeof(buf));

    int i=0;
    char *ptr = &buf[0];

    while (1) {
    if (i == sizeof(buf))
    break;

    char byte = *ptr++; /* *** (1) *** */
    printf("%c", byte);
    ++i;
    }
    printf("\n");
    return 0;
    }

    // ----------- end code

    In the last iteration of the loop, ptr will point past the last byte
    of memory allocated for this array. This is a contrived example, but
    I just wanted to know whether it's ok to point past the valid memory
    for this array as long as I don't read or modify the contents of
    memory at that address afterwards. On the surface it seems like this
    code won't cause me any problems.

    Thanks,

    Prashant

  • Scott Fluhrer

    #2
    Re: Pointing past valid memory


    <jois.de.vivre@ gmail.comwrote in message
    news:1183499219 .881427.198490@ d30g2000prg.goo glegroups.com.. .
    Hello, I was wondering if the following code was ok:
    >
    // ----------- start code
    >
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    >
    int main(int argc, char** argv)
    {
    char buf[10];
    memset(buf, 'a', sizeof(buf));
    >
    int i=0;
    char *ptr = &buf[0];
    >
    while (1) {
    if (i == sizeof(buf))
    break;
    >
    char byte = *ptr++; /* *** (1) *** */
    printf("%c", byte);
    ++i;
    }
    printf("\n");
    return 0;
    }
    >
    // ----------- end code
    >
    In the last iteration of the loop, ptr will point past the last byte
    of memory allocated for this array. This is a contrived example, but
    I just wanted to know whether it's ok to point past the valid memory
    for this array as long as I don't read or modify the contents of
    memory at that address afterwards. On the surface it seems like this
    code won't cause me any problems.
    Yes, that's safe. The Standard specifically allows you to set a pointer to
    just past the end of an array (with the provisio that you pointed out; that
    you don't actually reference that location).

    --
    poncho


    Comment

    • tguclu

      #3
      Re: Pointing past valid memory

      Hi,

      If your concern by saying "point past the valid memory " is ,
      Would it cause a problem to point an unallocated location ? Yes it
      would. Because line notated by /* *** (1) *** */ , post-increases
      ptr and in the final loop ptr will show next adjacent memory
      location.But we did't allocate any place for this location and we
      don't know what lies in it.

      But looking at your implementation , this would cause no problem
      because you don't use ptr anywhere else.





      On Jul 4, 12:46 am, jois.de.vi...@g mail.com wrote:
      Hello, I was wondering if the following code was ok:
      >
      // ----------- start code
      >
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      >
      int main(int argc, char** argv)
      {
      char buf[10];
      memset(buf, 'a', sizeof(buf));
      >
      int i=0;
      char *ptr = &buf[0];
      char *ptr = buf ; //this would do the same
      >
      while (1) {
      if (i == sizeof(buf))
      break;
      >
      char byte = *ptr++; /* *** (1) *** */
      printf("%c", byte);
      ++i;
      }
      printf("\n");
      return 0;
      >
      }
      >
      // ----------- end code
      >
      In the last iteration of the loop, ptr will point past the last byte
      of memory allocated for this array. This is a contrived example, but
      I just wanted to know whether it's ok to point past the valid memory
      for this array as long as I don't read or modify the contents of
      memory at that address afterwards. On the surface it seems like this
      code won't cause me any problems.
      >
      Thanks,
      >
      Prashant

      Comment

      • Keith Thompson

        #4
        Re: Pointing past valid memory

        tguclu <tugrul.guclu@g mail.comwrites:
        If your concern by saying "point past the valid memory " is ,
        Would it cause a problem to point an unallocated location ? Yes it
        would. Because line notated by /* *** (1) *** */ , post-increases
        ptr and in the final loop ptr will show next adjacent memory
        location.But we did't allocate any place for this location and we
        don't know what lies in it.
        >
        But looking at your implementation , this would cause no problem
        because you don't use ptr anywhere else.
        [...]

        Please don't top-post. Read the following for more information:




        I think you've misunderstood the rules about pointers.

        Creating a pointer value that points just past the end of an array is
        legal. (The standard explicitly allows this as a special case,
        because it's useful for some algorithms.) Attempting to dereference
        such a pointer invokes undefined behavior.

        Creating a pointer value that points *beyond* the end of an array, or
        before its beginning, invokes undefined behavior. Just creating such
        a pointer value invokes UB, even if you don't dereference it.

        --
        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."
        -- Antony Jay and Jonathan Lynn, "Yes Minister"

        Comment

        • pete

          #5
          Re: Pointing past valid memory

          jois.de.vivre@g mail.com wrote:
          while (1) {
          if (i == sizeof(buf))
          break;
          The non bizarre way of writing that, is:

          while (i != sizeof(buf)) {

          --
          pete

          Comment

          • Army1987

            #6
            Re: Pointing past valid memory


            <jois.de.vivre@ gmail.comha scritto nel messaggio news:1183499219 .881427.198490@ d30g2000prg.goo glegroups.com.. .
            Hello, I was wondering if the following code was ok:
            >
            // ----------- start code
            >
            #include <stdio.h>
            #include <stdlib.h>
            #include <string.h>
            >
            int main(int argc, char** argv)
            {
            char buf[10];
            memset(buf, 'a', sizeof(buf));
            >
            int i=0;
            char *ptr = &buf[0];
            >
            while (1) {
            if (i == sizeof(buf))
            break;
            >
            char byte = *ptr++; /* *** (1) *** */
            printf("%c", byte);
            ++i;
            }
            printf("\n");
            return 0;
            }
            >
            // ----------- end code
            >
            In the last iteration of the loop, ptr will point past the last byte
            of memory allocated for this array. This is a contrived example, but
            for (ptr = buf; ptr < buf + sizeof(buf); ptr++)
            putchar(*ptr);
            is far less contrived, but it is perfectly equivalent.
            I just wanted to know whether it's ok to point past the valid memory
            for this array as long as I don't read or modify the contents of
            memory at that address afterwards. On the surface it seems like this
            code won't cause me any problems.
            Yes, but only immediately past the last element. For example (buf + 10) is a valid pointer, even if you can't dereference it, but
            (buf
            + 11) has undefined behaviour.


            Comment

            • Army1987

              #7
              Re: Pointing past valid memory


              "tguclu" <tugrul.guclu@g mail.comha scritto nel messaggio news:1183500539 .498659.269670@ c77g2000hse.goo glegroups.com.. .
              [top-posting fixed]
              On Jul 4, 12:46 am, jois.de.vi...@g mail.com wrote:
              >Hello, I was wondering if the following code was ok:
              >>
              >// ----------- start code
              >>
              >#include <stdio.h>
              >#include <stdlib.h>
              >#include <string.h>
              >>
              >int main(int argc, char** argv)
              >{
              > char buf[10];
              > memset(buf, 'a', sizeof(buf));
              >>
              > int i=0;
              > char *ptr = &buf[0];
              char *ptr = buf ; //this would do the same
              >>
              > while (1) {
              > if (i == sizeof(buf))
              > break;
              >>
              > char byte = *ptr++; /* *** (1) *** */
              > printf("%c", byte);
              > ++i;
              > }
              > printf("\n");
              > return 0;
              >>
              >}
              >>
              >// ----------- end code
              >>
              >In the last iteration of the loop, ptr will point past the last byte
              >of memory allocated for this array. This is a contrived example, but
              >I just wanted to know whether it's ok to point past the valid memory
              >for this array as long as I don't read or modify the contents of
              >memory at that address afterwards. On the surface it seems like this
              >code won't cause me any problems.
              Hi,
              >
              If your concern by saying "point past the valid memory " is ,
              Would it cause a problem to point an unallocated location ? Yes it
              would. Because line notated by /* *** (1) *** */ , post-increases
              ptr and in the final loop ptr will show next adjacent memory
              location.But we did't allocate any place for this location and we
              don't know what lies in it.
              >
              But looking at your implementation , this would cause no problem
              because you don't use ptr anywhere else.
              Only because it is just past the end of buf. If it were any
              further, it'd cause UB. (Yes, I don't believe on your machine
              that'd cause problems if you computed buf + 16 without ever
              dereferencing it, but it's something I would not do on a DS9K.)


              Comment

              • Army1987

                #8
                Re: Pointing past valid memory


                "pete" <pfiland@mindsp ring.comha scritto nel messaggio news:468B11F8.5 665@mindspring. com...
                jois.de.vivre@g mail.com wrote:
                >
                > while (1) {
                > if (i == sizeof(buf))
                > break;
                >
                The non bizarre way of writing that, is:
                >
                while (i != sizeof(buf)) {
                Or
                for( ; i < sizeof buf ; ) {

                and i = 0 before the loop and ++i at the end of its body can then
                be moved to more appropriate places.


                Comment

                • Manish Tomar

                  #9
                  Re: Pointing past valid memory

                  Yes, but only immediately past the last element. For example (buf + 10) is a valid pointer, even if you can't dereference it, but
                  (buf
                  + 11) has undefined behaviour.
                  Why should this cause undefined behaviour if it is not accessed.
                  Pointer just happens to be another variable storing address instead of
                  any other data. As long as it stores data within its range (i.e. say
                  32-bit address) i dont think it should give undefined behaviour as
                  long as it is not accessed. In that case the following lines should
                  have undefined behaviour:

                  int *p = NULL; // points to 0, invalid mem
                  int *p; // store garbage address which may / may not be correct

                  (buff + 11) will just return a number. Thats it. Dont u think??

                  Regards,
                  Manish
                  (http://manishtomar.blogspot.com)

                  Comment

                  • Stephen Sprunk

                    #10
                    Re: Pointing past valid memory

                    "Manish Tomar" <manish.tomar@g mail.comwrote in message
                    news:1183549202 .823682.116490@ i38g2000prf.goo glegroups.com.. .
                    >Yes, but only immediately past the last element. For example
                    >(buf + 10) is a valid pointer, even if you can't dereference it,
                    >but (buf + 11) has undefined behaviour.
                    >
                    Why should this cause undefined behaviour if it is not accessed.
                    Because the Standard says so.
                    Pointer just happens to be another variable storing address
                    instead of any other data. As long as it stores data within its
                    range (i.e. say 32-bit address) i dont think it should give
                    undefined behaviour as long as it is not accessed.
                    Perhaps that's how it works on _your_ implementation. There are others
                    where pointers have special registers and even the creation or assignment of
                    an invalid pointer causes a trap, whether you dereference it or not. C
                    allows that behavior.
                    In that case the following lines should
                    have undefined behaviour:
                    >
                    int *p = NULL; // points to 0, invalid mem
                    NULL is a special case specifically allowed by the Standard.
                    int *p; // store garbage address which may / may not be correct
                    If you do anything with p other than assign a valid address or NULL to it,
                    you get UB.
                    (buff + 11) will just return a number. Thats it. Dont u think??
                    No, the Standard says that's UB, and so it is.

                    Just because your implementation treats pointers and integers the same under
                    the hood (and thus lets you get away with all sorts of things) doesn't mean
                    that all do. C runs on a lot of systems that aren't so forgiving...

                    S

                    --
                    Stephen Sprunk "Those people who think they know everything
                    CCIE #3723 are a great annoyance to those of us who do."
                    K5SSS --Isaac Asimov


                    --
                    Posted via a free Usenet account from http://www.teranews.com

                    Comment

                    • Chris Dollin

                      #11
                      Re: Pointing past valid memory

                      Manish Tomar wrote:
                      >Yes, but only immediately past the last element. For example (buf + 10) is a valid pointer, even if you can't dereference it, but
                      >(buf
                      >+ 11) has undefined behaviour.
                      >
                      Why should this cause undefined behaviour if it is not accessed.
                      Because the standard says so.
                      Pointer just happens to be another variable storing address instead of
                      any other data.
                      On some machines, actual machines that have existed and have had C
                      implementations , the restrictions on pointers are stronger than that.

                      In some implementations , such as those intended for debugging support,
                      pointers are more than "just addresses", and computing out-of-range
                      pointers will raise some kind of error.
                      As long as it stores data within its range (i.e. say
                      32-bit address) i dont think it should give undefined behaviour as
                      long as it is not accessed.
                      Nevertheless, some machine architectures did/do check, and the
                      C standard allows them to do so.

                      Note that "has undefined beahviour" doesn't mean "traps". It means
                      that the implementation is allowed to do /anything/. It may trap.
                      It may wrap. It may return zeroes. The Standard doesn't place any
                      constraints on the implementation at all.
                      In that case the following lines should
                      have undefined behaviour:
                      >
                      int *p = NULL; // points to 0, invalid mem
                      It does /not/ "point to 0". It's a /null pointer/; it doesn't
                      point anywhere.
                      int *p; // store garbage address which may / may not be correct
                      It has an indeterminate value; any use of it invokes undefined
                      behaviour.
                      (buff + 11) will just return a number. Thats it. Dont u think??
                      I don't think so -- but an implementation can legally do so if
                      that's convenient for it.

                      --
                      Hewlett-Packard Limited registered no:
                      registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England

                      Comment

                      • Flash Gordon

                        #12
                        Re: Pointing past valid memory

                        Manish Tomar wrote, On 04/07/07 12:40:
                        >Yes, but only immediately past the last element. For example (buf + 10) is a valid pointer, even if you can't dereference it, but
                        >(buf
                        >+ 11) has undefined behaviour.
                        >
                        Why should this cause undefined behaviour if it is not accessed.
                        Because the C standard says it does. As a programmer you really do not
                        need to know more than that.
                        Pointer just happens to be another variable storing address instead of
                        any other data. As long as it stores data within its range (i.e. say
                        32-bit address) i dont think it should give undefined behaviour as
                        long as it is not accessed. In that case the following lines should
                        have undefined behaviour:
                        >
                        int *p = NULL; // points to 0, invalid mem
                        No, it is a null pointer, it might point to some address other than 0 or
                        it might be something that does not actually point to anywhere at all.
                        int *p; // store garbage address which may / may not be correct
                        >
                        (buff + 11) will just return a number. Thats it. Dont u think??
                        Address are not necessarily just numbers, and the standard is written
                        the way it is to allow for implementations which can generate hardware
                        traps on invalid pointer arithmetic, or even on just loading an invalid
                        pointer, and crashes your program.
                        --
                        Flash Gordon

                        Comment

                        • christian.bau

                          #13
                          Re: Pointing past valid memory

                          On Jul 4, 12:40 pm, Manish Tomar <manish.to...@g mail.comwrote:
                          Yes, but only immediately past the last element. For example (buf + 10) is a valid pointer, even if you can't dereference it, but
                          (buf
                          + 11) has undefined behaviour.
                          >
                          Why should this cause undefined behaviour if it is not accessed.
                          Pointer just happens to be another variable storing address instead of
                          any other data. As long as it stores data within its range (i.e. say
                          32-bit address) i dont think it should give undefined behaviour as
                          long as it is not accessed. In that case the following lines should
                          have undefined behaviour:
                          >
                          int *p = NULL; // points to 0, invalid mem
                          int *p; // store garbage address which may / may not be correct
                          >
                          (buff + 11) will just return a number. Thats it. Dont u think??
                          (buff + 11) will not return a number, because there is no return
                          statement, and it will not yield a number, because if anything, it
                          would yield a pointer. Programming requires exactness, don't you
                          think?

                          If "int *p = (buff + 11) doesn't invoke undefined behaviour, it must
                          be defined behaviour, right? So what is that behaviour? Would you say
                          that for example p != NULL must yield a value of 1 (true), and that p
                          buff must yield a value of 1? Now what if we replace 11 with a
                          different numbers, say 12, or 100000, or 4000000000? Do you still
                          think that p buffer must yield a value of 1? If not, where would
                          this change?

                          "Undefined behaviour" means: The behaviour is not defined by the C
                          Standard. It doesn't matter whether you can imagine how something
                          undesired happens or not, what matters is whether the behaviour is
                          defined or not.

                          Now take this is a little challenge: Give an reasonable scenario where
                          a highly optimising compiler produces a very unexpected result if a
                          pointer expression (p + 11) is evaluated.

                          Comment

                          • Harald van =?UTF-8?B?RMSzaw==?=

                            #14
                            Re: Pointing past valid memory

                            christian.bau wrote:
                            Now take this is a little challenge: Give an reasonable scenario where
                            a highly optimising compiler produces a very unexpected result if a
                            pointer expression (p + 11) is evaluated.
                            #include <stdio.h>
                            #include <stdlib.h>

                            void g(void);

                            void f(void) {
                            char *p = malloc(10);
                            if (p == NULL) return;

                            p + 11;

                            for (;;) {
                            g();
                            printf("%c\n", p[10]);
                            }
                            }

                            void g(void) {
                            exit(0);
                            }

                            An optimising compiler may assume that because p+11 is evaluated, p+11 must
                            be a valid address, so p+10 must be dereferencable. As neither g nor printf
                            have any way of modifying p[10], the read of p[10] can be moved out of the
                            loop. And when p[10] is then evaluated, the program crashes.

                            A highly optimising compiler, on the other hand, would drop p entirely. :-)

                            Comment

                            • Manish Tomar

                              #15
                              Re: Pointing past valid memory

                              Thanks a lot guys for the response :). I haven't read the standard and
                              I didnt think from C implementation point of view. Now, I am clear
                              with it.

                              Comment

                              Working...