Memory alignment

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Why Tea

    #46
    Re: Memory alignment

    On Oct 4, 4:34 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
    Keith Thompson said:
    >
    Why Tea <ytl...@gmail.c omwrites:
    >
    <snip>
    >
    I understood it's bad and dangerous
    programming, but the question is can we be 100% sure that an
    existing code like that causes memory corruption? Based on the
    little I know, I don't think it's a simple answer of a YES or NO.
    >
    It is a very simple, but two-fold, answer - YES, you can be sure that
    writing into memory you don't own causes memory corruption; and NO, you
    can't be sure that the effect of this corruption will always be
    noticeable. When you write into memory you don't own, the behaviour of
    your program is undefined, and the rules of C no longer apply - so
    anything can happen, including (but by no means limited to) what you
    expected to happen.
    Thanks Richard. I understood what said. I'd like to apologize for
    asking for more questions. But I really would like to get to the
    bottom of this.

    If the memory is corrupted, wouldn't the system eventually crash
    if you run it long enough? If so, then we can be sure that the
    corruption will be noticeable.

    I went back to c-faq to read 2.6 many times again. I'll paste
    the code here for easy reference.

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

    struct name {
    int namelen;
    char namestr[1];
    };

    struct name *makename(char *newname)
    {
    struct name *ret =
    malloc(sizeof(s truct name)-1 + strlen(newname) +1);
    /* -1 for initial [1]; +1 for \0 */
    if(ret != NULL) {
    ret->namelen = strlen(newname) ;
    strcpy(ret->namestr, newname);
    }
    return ret;
    }

    Although not specifically stated, padding is likely
    to occur for namestr. So strcpy must have written into
    the padding bytes. The faq says "... has deemed that
    it is not strictly conforming with the C Standard,
    although it does seem to work under all known
    implementations ...".

    I know it's bad and it shouldn't be done. But when
    I look at tens of thousands of lines of code written
    by someone else and many of them make use of this
    hack. What can we conclude? Perhaps it does work,
    just like the faq says.

    I appreciate all of you who took the time to answer
    my questions. Not all of us work with C everyday,
    that's why we ask question here. Of course we try
    to google and ask our colleagues before turning to
    the group, but it doesn't always work - as this
    "struct hack" indicated. It doesn't help to answer
    the question with an almighty attitude, again as
    this "struct hack" has indicated, although the
    consensus is not to do it, but no one can say for
    sure if the system will eventually die or crash.
    Very often, we ask a question because we badly
    need help and we know there are many knowledgeable
    and competent people here. Thanks again for your
    time.
    That's why I think Antoninus has given a more accurate answer.
    >
    His answer is wrong. (See below.)
    >
    can't swear by the bible
    "It's not OK at all"
    >
    Um, did you read my answer, in which I specifically acknowledged that
    you can probably get away with accessing padding bytes but also
    explained why it's a bad idea to depend on it?
    >
    There is nothing "pragmatic" about encouraging you to assume that
    there are a certain number of padding bytes at the end of a structure,
    and that you can safely use them for whatever you want.
    >

    Comment

    • Richard Heathfield

      #47
      Re: Memory alignment

      Why Tea said:

      <snip>
      If the memory is corrupted, wouldn't the system eventually crash
      if you run it long enough?
      The C Standard does not guarantee this (either way).
      If so, then we can be sure that the
      corruption will be noticeable.
      >
      I went back to c-faq to read 2.6 many times again. I'll paste
      the code here for easy reference.
      >
      #include <stdlib.h>
      #include <string.h>
      >
      struct name {
      int namelen;
      char namestr[1];
      };
      >
      struct name *makename(char *newname)
      {
      struct name *ret =
      malloc(sizeof(s truct name)-1 + strlen(newname) +1);
      /* -1 for initial [1]; +1 for \0 */
      if(ret != NULL) {
      ret->namelen = strlen(newname) ;
      strcpy(ret->namestr, newname);
      }
      return ret;
      }
      >
      Although not specifically stated, padding is likely
      to occur for namestr. So strcpy must have written into
      the padding bytes.
      Well, actually strcpy has written into memory that you allocated via
      malloc.
      The faq says "... has deemed that
      it is not strictly conforming with the C Standard,
      although it does seem to work under all known
      implementations ...".
      dmr once called it "unwarrante d chumminess with the implementation" .
      I know it's bad and it shouldn't be done. But when
      I look at tens of thousands of lines of code written
      by someone else and many of them make use of this
      hack. What can we conclude?
      We can conclude that lots of people do bad things that shouldn't be done.
      Perhaps it does work, just like the faq says.
      As far as I'm aware, nobody has ever found an implementation on which the
      struct hack (i.e. the hack by which you allocate more storage than the
      structure actually needs) doesn't work. That is not the same as saying
      that it's okay to write into memory you don't own. It isn't and you
      shouldn't. Whether you do or not is your concern, but you can't blame the
      implementation if it all goes wrong.

      <snip>

      --
      Richard Heathfield <http://www.cpax.org.uk >
      Email: -http://www. +rjh@
      Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
      "Usenet is a strange place" - dmr 29 July 1999

      Comment

      • Nick Keighley

        #48
        Trolls [Was: Memory alignment]

        On 4 Oct, 06:34, Richard Heathfield <r...@see.sig.i nvalidwrote:
        Keith Thompson said:
        Why Tea <ytl...@gmail.c omwrites:
        <snip>
        "Antoninus Twink" is a troll.  Please do us all a favor and ignore
        him.
        >
        It is clear from the above that at least some newbies are *not* ignoring
        the technically incompetent answers provided by Mr Twink. Note that
        "technicall y incompetent" and "trollish" are not the same thing. The
        problem with Mr Twink (and it is not a problem that is unique to him) is
        that he's *both*. The regular contributors to this group know full well
        that he's a troll. He is in many killfiles (including mine). And therefore
        he can often get away with spouting any old rubbish without being
        challenged, and thus newbies can be misled into following his "advice" (as
        appears to have happened in this case).
        which is why I don't have him kill filed.

        <snip>
        So the killfile "solution" is problematic, because it allows trolls like Mr
        Twink the freedom to give stupid advice to up-lapping newbies with little
        or no risk of being corrected. Unfortunately, the non-killfile "solution"
        is also problematic, because it raises the overall temperature of the
        group. If, for example, I were to remove Mr Twink from my killfile, I know
        from experience that within a week there'd be a flame war several hundreds
        of articles long.
        my rule of two (or sometimes 3) hopefully keeps me from this.
        I me and my protagonist have repeated the same position three
        then I declare it a stalemate and retire from the discussion.
        The analogy is with similar chess rule.

        I usually try to avoid replying to Twink but instead reply
        to his repliers. Sometimes he's so potentially misleading
        I feel I have to respond for the sake of the lurkers.

        <snip>

        Kenny's easier as he's just tedious.

        --
        Nick Keighley

        Comment

        • Keith Thompson

          #49
          Re: Memory alignment

          Why Tea <ytlim1@gmail.c omwrites:
          On Oct 4, 4:34 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
          >Keith Thompson said:
          >>
          Why Tea <ytl...@gmail.c omwrites:
          >>
          ><snip>
          >>
          >I understood it's bad and dangerous
          >programming, but the question is can we be 100% sure that an
          >existing code like that causes memory corruption? Based on the
          >little I know, I don't think it's a simple answer of a YES or NO.
          >>
          >It is a very simple, but two-fold, answer - YES, you can be sure that
          >writing into memory you don't own causes memory corruption; and NO, you
          >can't be sure that the effect of this corruption will always be
          >noticeable. When you write into memory you don't own, the behaviour of
          >your program is undefined, and the rules of C no longer apply - so
          >anything can happen, including (but by no means limited to) what you
          >expected to happen.
          >
          Thanks Richard. I understood what said. I'd like to apologize for
          asking for more questions. But I really would like to get to the
          bottom of this.
          >
          If the memory is corrupted, wouldn't the system eventually crash
          if you run it long enough? If so, then we can be sure that the
          corruption will be noticeable.
          Maybe, maybe not. There are no guarantees, one way or the other.

          For example, if by "corrupting memory" you clobber the value of some
          other variable, maybe it's a variable that isn't used again, so it has
          no visible effect on the program. Or maybe you clobber memory that's
          outside the object you're trying to access, but also outside any other
          object. Or maybe you set some variable to a value that happens to be
          correct.

          There are any number of ways you can corrupt memory with no visible
          effect. The risk is that the effect could become visible at the least
          convenient possible time -- say, when your software has been deployed
          to customers, or when you're demonstrating it to somebody important,
          or years later when all the people who are familiar with the code have
          left the company. Such is the nature of undefined behavior.
          I went back to c-faq to read 2.6 many times again. I'll paste
          the code here for easy reference.
          >
          #include <stdlib.h>
          #include <string.h>
          >
          struct name {
          int namelen;
          char namestr[1];
          };
          >
          struct name *makename(char *newname)
          {
          struct name *ret =
          malloc(sizeof(s truct name)-1 + strlen(newname) +1);
          /* -1 for initial [1]; +1 for \0 */
          if(ret != NULL) {
          ret->namelen = strlen(newname) ;
          strcpy(ret->namestr, newname);
          }
          return ret;
          }
          >
          Although not specifically stated, padding is likely
          to occur for namestr. So strcpy must have written into
          the padding bytes. The faq says "... has deemed that
          it is not strictly conforming with the C Standard,
          although it does seem to work under all known
          implementations ...".
          Proper use of the struct hack does *not* depend on padding bytes. It
          writes outside the bounds of the array, and of the struct that
          contains it, but *within* the bounds of the chunk of memory allocated
          by malloc. For this to work, you need an implementation that doesn't
          do bounds checking; almost all existing implementations qualify. (In
          fact, since the struct hack is a common trick, a compiler that broke
          it would probably fail in the marketplace.)

          On the other hand, there's some risk that an optimizing compiler could
          cause problems. Since violating array bounds invokes undefined
          behavior, an optimizing compiler is allowed to *assume* that you
          haven't done so, even if it doesn't generate code for explicit
          run-time bounds checks. But again, the struct hack is common enough
          that you should be ok.
          I know it's bad and it shouldn't be done. But when
          I look at tens of thousands of lines of code written
          by someone else and many of them make use of this
          hack. What can we conclude? Perhaps it does work,
          just like the faq says.
          The struct hack itself *probably* violates the rules of the language,
          but it's generally supported -- and C99 explicitly supports it in a
          different form. Code that assumes the presence of padding bytes, on
          the other hand, is more dangerous. For example, if your declaration
          changes from this:
          struct name {
          int namelen;
          char namestr[1];
          };
          to this:
          struct name {
          int namelen;
          short something;
          unsigned char something_else;
          char namestr[1];
          };
          then it's likely (given 4-byte int, 2-byte short, and, of course,
          1-byte char) that the structure will be 8 bytes with *no* padding.

          There might be some confusion here. I haven't gone back to the
          original article, and I'm not certain that the code you originally
          posted actually assumed the existence of padding bytes rather than
          just making ordinary use of the struct hack.

          [...]

          --
          Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
          Nokia
          "We must do something. This is something. Therefore, we must do this."
          -- Antony Jay and Jonathan Lynn, "Yes Minister"

          Comment

          • Nick Keighley

            #50
            Re: Memory alignment

            On 4 Oct, 09:57, Antoninus Twink <nos...@nospam. invalidwrote:
            On 4 Oct 2008 at 5:02, Keith Thompson wrote:
            There is nothing "pragmatic" about encouraging you to assume that
            there are a certain number of padding bytes at the end of a structure,
            and that you can safely use them for whatever you want.
            >
            Why don't you get off your high horse for a minute and try to separate
            the two issues in your mind?
            >
            The question you're addressing is: Is it OK to make certain padding
            assumptions about structs, and based on those assumptions to write to
            memory beyond the last field in the struct? The answer is, of course
            that's not a good idea in general, and I'd never advise anyone to do it.
            ok
            But that wasn't what the OP was asking. He was talking about a specific
            compiler on a specific system,
            and perhaps he should have asked on a specifc news group
            where he'd verified that there were some
            number of padding bytes at the end of the struct. He asked, in that
            specific situation, whether writing into those padding bytes could cause
            his program to blow up?
            >
            The pragmatic answer is no,
            only if "pragmatic" means "wrong". The problem is his program is now
            non-portable. This non-portability *could* involve different compilers
            on the same platform. Or different versions of the same compiler.
            Or changes to flag settings of the compiler (particularly
            optimistation
            flags).

            Its quite easier for you to end up writing to bytes that
            don't belong to you. And that's an accident waiting to happen.

            unless (as someone else pointed out) the
            compiler comes with some elaborate bounds-checking "feature", a
            possibility which for all practical purposes can be ignored, because
            it's vanishingly unlikely.
            >
            struct foo *p = malloc(sizeof(s truct foo));
            char *q = (char *) p;
            q[sizeof(struct foo) - 1]=0;
            >
            Are you seriously saying that there's any real-world system that will
            blow up here if it happens that there's padding at the end of struct
            foo?
            no no-one knows of one. The standard commitee still doesn't think
            highly of the "struct hack" of which this a variant.


            --
            Nick Keighley
            "Almost every species in the universe has an irrational fear of the
            dark.
            But they're wrong- cos it's not irrational. It's Vashta Nerada."
            The Doctor

            Comment

            • Nick Keighley

              #51
              Re: Memory alignment

              On 3 Oct, 20:57, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
              Why Tea <ytl...@gmail.c omwrites:
              On Oct 3, 12:48 pm, danmat...@gmail .com wrote:
              But strcpy(my->struct->s, "AB"); is OK if there is
              padding. Isn't it not? Please go easy on me here.
              I just want to understand how this really works...
              >
              It will, but if you add a new elemnt at the end of the structure later
              on in might not, you might overwrite the next element.
              >
              Why would you want to declare a 1 char array to store 2 anyway?
              >
              Good question. This is found in some real embedded
              code to make more efficient of the memory. As I understood
              it, the last s[1] is just a placeholder as you can
              allocate more memory when needed. For example:
              >
              my_struct = malloc(sizeof(m y_struct_t) + MY_PAYLOAD_STRI NG_SIZE);
              >
              This is called the "struct hack". It has been formalised in C99 so if
              you can use C99 then all will be well.
              um. I thought the position of the struct hack was the same
              on C99 as C90. What *did* change was the addiition of
              VLAs that were intended to remove the need for TSH

              The same my_struct_t is used throughout the code for
              signal sending. If s[] is used to carry binary data, the
              size is specified by an int preceding s[]. I'd be
              interested to hear comments from the experts about
              this approach.
              >
              It is considered to be "a bit dodgy" (that is the technical term) but
              it generally works. I am not sure there is really much more to say
              about it though I get the feeling I will be proved very much wrong
              about that!
              I think on a reasonably sane embedded system it was almost
              certain it would work. Obviously you run some tests. I've used
              TSH heavily.

              --
              Nick Keighley

              "If, indeed the subatomic energy in the stars is being freely
              used to maintain their great furnaces, it seems to bring a little
              nearer to fulfillment our dreams of controlling this latent
              power for the well-being of the human race - or for its suicide."
              Aurthur S. Eddington "The Internal Constitution of the Stars" 1926

              Comment

              • Antoninus Twink

                #52
                Re: Memory alignment

                On 6 Oct 2008 at 7:44, Nick Keighley wrote:
                On 4 Oct, 09:57, Antoninus Twink <nos...@nospam. invalidwrote:
                >where he'd verified that there were some
                >number of padding bytes at the end of the struct. He asked, in that
                >specific situation, whether writing into those padding bytes could cause
                >his program to blow up?
                >>
                >The pragmatic answer is no,
                >
                only if "pragmatic" means "wrong". The problem is his program is now
                non-portable. This non-portability *could* involve different compilers
                on the same platform. Or different versions of the same compiler. Or
                changes to flag settings of the compiler (particularly optimistation
                flags).
                The OP knows that perfectly well, and it isn't what he was asking:
                >>if there is a system crash in an embedded system and the dump shows
                >>it was due to a wild pointer. When you see a piece of code that uses
                >>the struct hack (a term I just learned) and it forgets to include
                >>the '\0' in the size allocated, you can't really swear by the bible
                >>that it causes the crash as it over steps the memory allocated with
                >>strcpy. I understood it's bad and dangerous programming, but the
                >>question is can we be 100% sure that an existing code like that
                >>causes memory corruption?
                The answer is NO, we can't be 100% sure that struct-hack-like code
                caused the problem. In fact, we can be 99% sure that it didn't.

                Comment

                • James Kuyper

                  #53
                  Re: Memory alignment

                  Why Tea wrote:
                  ....
                  If the memory is corrupted, wouldn't the system eventually crash
                  if you run it long enough? If so, then we can be sure that the
                  corruption will be noticeable.
                  No. Instead of crashing, the system could also get stuck in an infinite
                  loop. However, the truly insidious possibility is that your program will
                  continue apparently normally and exit without showing any obvious signs.
                  That doesn't mean that it worked correctly; it might produce output that
                  is subtly wrong in some way, or it might produce a catastrophic error,
                  but with only a 1% chance of triggering the catastrophe during any
                  particular run of the program. It could run a long time, generating lots
                  of subtly erroneous data that will require a lot of work to fix, before
                  you even notice the problem.

                  ....
                  I know it's bad and it shouldn't be done. But when
                  I look at tens of thousands of lines of code written
                  by someone else and many of them make use of this
                  hack. What can we conclude? Perhaps it does work,
                  just like the faq says.
                  The struct hack does work, on most C90 systems, and I would not
                  recommend worrying too much about the possibility of it failing unless
                  and until you find that it fails on a particular system that you need to
                  port it to. However, don't make any important decisions based upon the
                  assumption that it can't fail - in principle it can, and you need to
                  remember that.

                  C99 flexible arrays will work on any fully conforming implementation of
                  C99, and on many implementations that fall short of full conformance.
                  I'd recommend using flexible arrays rather than the struct hack, if
                  you're able to restrict the portability of your program to those
                  implementations that support it, and to complain about the ones that
                  don't support it. As a practical matter, any implementation that lets
                  you declare a flexible array member without generating a diagnostic will
                  almost certainly support correct use of that member. Thus, you'll learn
                  at compile time, rather than run time, whether or not you'll be able to
                  use it safely.

                  However, flexible array members are still not universally supported. The
                  difference is, if the struct hack fails, the implementor can point to
                  sections of the standard that allow it to fail. If flexible arrays are
                  not supported, you can point to sections of C99 standard that require
                  them to be. That won't necessarily make it any easier to convince the
                  implementor to change their implementation, but it is a stronger argument.

                  Comment

                  • James Kuyper

                    #54
                    Re: Memory alignment

                    Nick Keighley wrote:
                    On 3 Oct, 20:57, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
                    ....
                    >This is called the "struct hack". It has been formalised in C99 so if
                    >you can use C99 then all will be well.
                    >
                    um. I thought the position of the struct hack was the same
                    on C99 as C90. What *did* change was the addiition of
                    VLAs that were intended to remove the need for TSH
                    No, the relevant change was not VLAs, but flexible array members. They
                    work almost exactly like the struct hack, except that instead of
                    declaring a specific length for the array, the length is left
                    unspecified. The key point is that the behavior of flexible array
                    members is defined by the standard, the behavior when using the struct
                    hack is not.

                    Comment

                    • Why Tea

                      #55
                      Re: Memory alignment

                      On Oct 5, 10:22 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
                      Why Tea said:
                      >
                      <snip>
                      >
                      If the memory is corrupted, wouldn't the system eventually crash
                      if you run it long enough?
                      >
                      The C Standard does not guarantee this (either way).
                      >
                      >
                      >
                      If so, then we can be sure that the
                      corruption will be noticeable.
                      >
                      I went back to c-faq to read 2.6 many times again. I'll paste
                      the code here for easy reference.
                      >
                      #include <stdlib.h>
                      #include <string.h>
                      >
                      struct name {
                        int namelen;
                        char namestr[1];
                      };
                      >
                      struct name *makename(char *newname)
                      {
                        struct name *ret =
                            malloc(sizeof(s truct name)-1 + strlen(newname) +1);
                                           /* -1 for initial [1]; +1 for \0 */
                        if(ret != NULL) {
                          ret->namelen = strlen(newname) ;
                          strcpy(ret->namestr, newname);
                        }
                        return ret;
                      }
                      >
                      Although not specifically stated, padding is likely
                      to occur for namestr. So strcpy must have written into
                      the padding bytes.
                      >
                      Well, actually strcpy has written into memory that you allocated via
                      malloc.
                      >
                      Does "strcpy(ret->namestr, newname);" really copy data
                      into the memory malloc'ed? I have a mental picture of
                      this for namestr:

                      Byte #1 is declared, 2-4 could be padding assuming
                      32 bit alignment.
                      1 2 3 4 5 6 7 8 9 10 11 ...
                      |<->|<---- malloc'ed ...--->

                      Doesn't 'strcpy(ret->namestr, "Richard"); " become
                      this?
                      1 2 3 4 5 6 7 8 9
                      R i c h a r d \0
                      Perhaps it does work, just like the faq says.
                      >
                      As far as I'm aware, nobody has ever found an implementation on which the
                      struct hack (i.e. the hack by which you allocate more storage than the
                      structure actually needs) doesn't work. That is not the same as saying
                      that it's okay to write into memory you don't own. It isn't and you
                      shouldn't. Whether you do or not is your concern, but you can't blame the
                      implementation if it all goes wrong.
                      Understood.

                      Comment

                      • lawrence.jones@siemens.com

                        #56
                        Re: Memory alignment

                        Keith Thompson <kst-u@mib.orgwrote:
                        >
                        Fair enough. I *know* it's called the "struct hack", and I've read
                        question 2.6 before, but I had trouble finding it myself, since the
                        answer to 2.6 doesn't use the phrase "struct hack".
                        That's the kind of thing that makes creating a good index difficult.
                        It's also why the index in the C standard contains terms that don't
                        appear anywhere else in the document (including "struct hack", I'm
                        glad to say).
                        --
                        Larry Jones

                        I wonder if you can refuse to inherit the world. -- Calvin

                        Comment

                        • Ben Bacarisse

                          #57
                          Re: Memory alignment

                          Why Tea <ytlim1@gmail.c omwrites:
                          On Oct 5, 10:22 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
                          >Why Tea said:
                          <snip>
                          #include <stdlib.h>
                          #include <string.h>
                          >>
                          struct name {
                            int namelen;
                            char namestr[1];
                          };
                          >>
                          struct name *makename(char *newname)
                          {
                            struct name *ret =
                                malloc(sizeof(s truct name)-1 + strlen(newname) +1);
                                               /* -1 for initial [1]; +1 for \0 */
                            if(ret != NULL) {
                              ret->namelen = strlen(newname) ;
                              strcpy(ret->namestr, newname);
                            }
                            return ret;
                          }
                          >>
                          Although not specifically stated, padding is likely
                          to occur for namestr. So strcpy must have written into
                          the padding bytes.
                          >>
                          >Well, actually strcpy has written into memory that you allocated via
                          >malloc.
                          >>
                          >
                          Does "strcpy(ret->namestr, newname);" really copy data
                          into the memory malloc'ed?
                          Yes.
                          I have a mental picture of
                          this for namestr:
                          >
                          Byte #1 is declared, 2-4 could be padding assuming
                          32 bit alignment.
                          1 2 3 4 5 6 7 8 9 10 11 ...
                          |<->|<---- malloc'ed ...--->
                          It is all malloced, including some other bytes that are used for
                          namelen.
                          Doesn't 'strcpy(ret->namestr, "Richard"); " become
                          this?
                          1 2 3 4 5 6 7 8 9
                          R i c h a r d \0
                          Yes, if by this you mean that the letters get put in the first (and
                          only) byte of namestr and then in consecutive following bytes. The
                          fact that some of these bytes might be due to sizeof *ret being >
                          sizeof ret->namelen + 1 does not mean they are not malloced or that you
                          can't write to them.

                          The main problems with the struct hack come from maintaining the
                          code. Everyone using the structure has to know that the size is "fake"
                          and that it can't be zeroed and copied like other structures.

                          BTW, I'd number these from 0 rather than 1 just to be consistent with
                          offsets and C's array indexes.

                          --
                          Ben.

                          Comment

                          • Lowell Gilbert

                            #58
                            Re: Memory alignment

                            Keith Thompson <kst-u@mib.orgwrites :
                            Eric Sosman <Eric.Sosman@su n.comwrites:
                            >Keith Thompson wrote:
                            >>Lowell Gilbert <lgusenet@be-well.ilk.orgwri tes:
                            >>>Why Tea <ytlim1@gmail.c omwrites:
                            >>>>On Oct 3, 12:48 pm, danmat...@gmail .com wrote:
                            >>[...]
                            >>>>>Why would you want to declare a 1 char array to store 2 anyway?
                            >>>>Good question. This is found in some real embedded
                            >>>>code to make more efficient of the memory. As I understood
                            >>>>it, the last s[1] is just a placeholder as you can
                            >>>>allocate more memory when needed. For example:
                            >>>>>
                            >>>>my_struct = malloc(sizeof(m y_struct_t) + MY_PAYLOAD_STRI NG_SIZE);
                            >>>or even more likely, something more like
                            >>> my_struct = malloc(sizeof(m y_struct_t) + strlen(my->struct->s));
                            >>+ 1. The length returned by strlen() doesn't include the
                            >>terminating '\0'.
                            >>
                            > The struct has `char s[1]' as its last element[*], and the
                            >size of that element is already included in sizeof(my_struc t_t).
                            >
                            So it does.
                            >
                            Seeing strlen() in a computation of how much memory to allocate sets
                            off my alarm bells. If I were going to write something like that in
                            real code, it would be heavily commented.
                            Sure.

                            What I was really trying to point out was that the malloc() length
                            won't be the same all the time, or else you wouldn't use the struct
                            hack to begin with.

                            --
                            Lowell Gilbert, embedded/networking software engineer

                            Comment

                            • Tim Rentsch

                              #59
                              Re: Memory alignment

                              lawrence.jones@ siemens.com writes:
                              Antoninus Twink <nospam@nospam. invalidwrote:

                              Yes, of course, if there are two or more padding bytes at the end of the
                              struct then that's your memory to write to, whether it's on the stack if
                              my_struct is an automatic variable, or on the heap if you got the memory
                              from malloc().
                              >
                              No, the padding bytes are most definitely *not* yours to write to.
                              Although most implementations will let you get away with it, there are
                              implementations that do careful memory bounds checking and won't.
                              I'm sure someone with Larry Jones's credentials must be saying
                              something by this, but I'll be darned if I know what it is. Surely
                              padding bytes must be available for writing to, at least as unsigned
                              char, so functions with a qsort-like interface can be written.

                              Comment

                              • Keith Thompson

                                #60
                                Re: Memory alignment

                                Tim Rentsch <txr@alumnus.ca ltech.eduwrites :[...]
                                >No, the padding bytes are most definitely *not* yours to write to.
                                >Although most implementations will let you get away with it, there are
                                >implementation s that do careful memory bounds checking and won't.
                                >
                                I'm sure someone with Larry Jones's credentials must be saying
                                something by this, but I'll be darned if I know what it is. Surely
                                padding bytes must be available for writing to, at least as unsigned
                                char, so functions with a qsort-like interface can be written.
                                The context was a discussion of the struct hack. For example, given:

                                struct h {
                                int i;
                                char arr[1];
                                };
                                struct h obj;

                                Assume:
                                sizeof(int)==4
                                sizeof(struct h)==8
                                offsetof(struct h, arr)==4.

                                Then:

                                obj.arr[0] is perfectly ok

                                obj.arr[1] is potentially problematic in several ways:

                                1. Accessing obj.arr beyond its bounds is UB (but in practice will
                                cause problems only if the implementation does bounds checking).

                                2. Assuming no array bounds checking, accessing a nonexistent element
                                of obj.arr that happens to overlay a padding byte probably won't
                                cause problems in practice, but if the struct declaration is
                                changed, or if the code is compiled under a different
                                implementation, there might not be a padding byte there.

                                But if, rather than a single declare object obj, you're accessing the
                                arr member of a struct h object allocated via malloc(), where malloc()
                                was carefully called to allocate enough extra memory for however many
                                elements of arr you need, then ptr->arr[1] is almost certainly ok.
                                It's strictly UB, and it would break on a strict bounds-checking
                                implementation, but the struct hack is commonly used in practice.
                                It's safe to assume (though not guaranteed by the standard) that there
                                will at least be a way to turn off any bounds checking if you need to.

                                Treating the structure as an array of unsigned char, and accessing
                                those bytes, including any padding bytes, is ok.

                                Assuming that there are one or more padding bytes is non-portable
                                (and, in my opinion, unnecessary and poor style).

                                --
                                Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                                Nokia
                                "We must do something. This is something. Therefore, we must do this."
                                -- Antony Jay and Jonathan Lynn, "Yes Minister"

                                Comment

                                Working...