Variable length arrays

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Erwin Lindemann

    Variable length arrays


    If a VLA appears within a loop body, it seems the behavior is
    different with two different compilers I tried. I looked at the
    standard text, but couldn't find a definite answer there either.

    Consider the following test program

    /* begin foo.c */
    #include <stdio.h>
    #include <string.h>

    void test(int n, size_t size)
    {
    int i;

    for(i = 0; i < n; i++) {
    unsigned char vla[size];
    memset(vla, (i & 255), size);
    printf("step %d: vla=%p\n", i, &vla[0]);
    }
    }

    int main(void)
    {
    test(10, 256*1024L);
    return 0;
    }
    /* end foo.c */

    With gcc, 'vla' is reused in every iteration, i.e., the address
    of 'vla[0]' is identical in every step.

    However, with lcc-win32, output is as follows...

    step 0: vla=0x002ffea0
    step 1: vla=0x002bfea0
    step 2: vla=0x0027fea0
    step 3: vla=0x0023fea0
    [*CRASH*]

    , meaning, new storage is allocated for 'vla' at every iteration,
    eventually exhausting all available auto storage.

    Now, is this just implementation dependant and this kind of construct
    should be avoided, or is one of these compilers not working correctly?

    Should a bug report be filed?

    Thanks
    --
    Erwin Lindemann
  • Jack Klein

    #2
    Re: Variable length arrays

    On Thu, 6 Mar 2008 02:38:17 +0100 (CET), Erwin Lindemann
    <elindema@wupp. invalidwrote in comp.lang.c:
    >
    If a VLA appears within a loop body, it seems the behavior is
    different with two different compilers I tried. I looked at the
    standard text, but couldn't find a definite answer there either.
    There is no definitive answer. All the standard says about VLAs that
    might be relevant is this:

    "For such an object that does have a variable length array type, its
    lifetime extends from the declaration of the object until execution of
    the program leaves the scope of the declaration. If the scope is
    entered recursively, a new instance of the object is created each
    time. The initial value of the object is indeterminate."

    It says nothing at all about whether each creation must, may, or may
    not have the same address. So it is entirely a QOI issue.
    Consider the following test program
    >
    /* begin foo.c */
    #include <stdio.h>
    #include <string.h>
    >
    void test(int n, size_t size)
    {
    int i;
    >
    for(i = 0; i < n; i++) {
    unsigned char vla[size];
    memset(vla, (i & 255), size);
    printf("step %d: vla=%p\n", i, &vla[0]);
    }
    }
    >
    int main(void)
    {
    test(10, 256*1024L);
    return 0;
    }
    /* end foo.c */
    >
    With gcc, 'vla' is reused in every iteration, i.e., the address
    of 'vla[0]' is identical in every step.
    >
    However, with lcc-win32, output is as follows...
    >
    step 0: vla=0x002ffea0
    step 1: vla=0x002bfea0
    step 2: vla=0x0027fea0
    step 3: vla=0x0023fea0
    [*CRASH*]
    >
    , meaning, new storage is allocated for 'vla' at every iteration,
    eventually exhausting all available auto storage.
    >
    Now, is this just implementation dependant and this kind of construct
    should be avoided, or is one of these compilers not working correctly?
    Since the standard does not require either behavior, it is not a
    conformance defect that I can see. It is a QOI issue, and I suggest
    you contact the offending compiler's implementer, either directly or
    on his support group.
    Should a bug report be filed?
    Since the standard does not guarantee that the creation of any array
    of automatic duration will succeed, even if it is not a VLA, it's hard
    to see a complaint on standard conformance grounds, but it's a huge
    QOI issue.

    I'd complain if I used this feature of his compiler, although I have
    plonked him and don't use his compiler at all anymore.

    Consider a similar case:

    #include <stdio.h>

    void func(int x)
    {
    printf("%p\n", (void *)&x;
    }

    int main(void)
    {
    int x = 0;
    func();
    func();
    func();
    return x;
    }

    I don't think I have ever used an implementation where the three calls
    to func() would output different values.

    Do you think the C standard requires it to be the same? If not, do
    you think it should?

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c++-faq-lite/
    alt.comp.lang.l earn.c-c++

    Comment

    • Micah Cowan

      #3
      Re: Variable length arrays

      Erwin Lindemann <elindema@wupp. invalidwrites:
      With gcc, 'vla' is reused in every iteration, i.e., the address
      of 'vla[0]' is identical in every step.
      >
      However, with lcc-win32, output is as follows...
      >
      step 0: vla=0x002ffea0
      step 1: vla=0x002bfea0
      step 2: vla=0x0027fea0
      step 3: vla=0x0023fea0
      [*CRASH*]
      >
      , meaning, new storage is allocated for 'vla' at every iteration,
      eventually exhausting all available auto storage.
      >
      Now, is this just implementation dependant and this kind of construct
      should be avoided, or is one of these compilers not working correctly?
      >
      Should a bug report be filed?
      I'd file it, yeah.

      6.2.4#6:

      "such an object" "does have"
      For [an object with automatic storage duration] that [has] a variable
      length array type, its lifetime extends from the declaration of the
      object until execution of the program leaves the scope of the
      declaration.

      --
      Micah J. Cowan
      Programmer, musician, typesetting enthusiast, gamer...

      Comment

      • jacob navia

        #4
        Re: Variable length arrays

        Jack Klein wrote:
        >
        I'd complain if I used this feature of his compiler, although I have
        plonked him and don't use his compiler at all anymore.
        >
        Consider a similar case:
        >
        #include <stdio.h>
        >
        void func(int x)
        {
        printf("%p\n", (void *)&x); // missing ")" fixed
        }
        >
        int main(void)
        {
        int x = 0;
        func();
        func();
        func();
        return x;
        }
        >
        I don't think I have ever used an implementation where the three calls
        to func() would output different values.
        >
        Do you think the C standard requires it to be the same? If not, do
        you think it should?
        >
        I am happy you do not use my compiler system since your
        buggy code will not even compile:

        Error tbb.c: 11 insufficient number of arguments to `func'
        Error tbb.c: 12 insufficient number of arguments to `func'
        Error tbb.c: 13 insufficient number of arguments to `func'
        3 errors, 0 warnings

        --
        jacob navia
        jacob at jacob point remcomp point fr
        logiciels/informatique

        Comment

        • Keith Thompson

          #5
          Re: Variable length arrays

          jacob navia <jacob@nospam.o rgwrites:
          Erwin Lindemann wrote:
          >If a VLA appears within a loop body, it seems the behavior is
          >different with two different compilers I tried. I looked at the
          >standard text, but couldn't find a definite answer there either.
          >>
          >
          There is no definite answer. It is implementation dependent.
          >
          >Consider the following test program
          >>
          >/* begin foo.c */
          >#include <stdio.h>
          >#include <string.h>
          >>
          >void test(int n, size_t size)
          >{
          > int i;
          >>
          > for(i = 0; i < n; i++) {
          > unsigned char vla[size]; //<<<<<<<<<<<<<<< <<
          > memset(vla, (i & 255), size);
          > printf("step %d: vla=%p\n", i, &vla[0]);
          > }
          >}
          >>
          >int main(void)
          >{
          > test(10, 256*1024L);
          > return 0;
          >}
          >/* end foo.c */
          >>
          >With gcc, 'vla' is reused in every iteration, i.e., the address
          >of 'vla[0]' is identical in every step.
          The standard doesn't say that "vla" must have the same address at
          every iteration of the loop, and it shouldn't matter whether it does
          or not. In fact, a strictly conforming program can't tell whether the
          same memory is re-used, since the address becomes invalid at the end
          of the block, when the lifetime of "vla" has ended.

          *However*, the lifetime of "vla" begins at its declaration and ends at
          the end of the block (the loop body). There's a distinct array object
          for each iteration of the loop, but the lifetimes of these objects do
          not overlap. Since the program apparently dies with an out-of-memory
          condition, it appears that the generated code is allocating space for
          "vla" at the point of declaration *and not deallocating it* at the end
          of the array's lifetime.

          An argument could probably be made that this behavior doesn't violate
          the standard, but it's certainly a bug. I don't care whether "vla"
          has the same address each time; I care that the program crashes.

          Consider:

          for (i = 0; i < n; i ++) {
          unsigned char arr[2000];
          /* ... */
          }

          Would it be acceptable for n copies of "arr" to have memory allocated
          for them simultaneously, causing the program to die? If not, why
          would it be acceptable for a VLA?

          Or perhaps I've misunderstood what's going on here. I don't have
          lcc-win, so I can't test it myself. jacob, can you explain why the
          program dies?

          [...]
          >Should a bug report be filed?
          IMHO, yes.
          You can only file a bug report if you buy maintenance at premium rates.
          I have a special price for clique members sorry!
          *Yawn*.

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

          Comment

          • SM Ryan

            #6
            Re: Variable length arrays

            Erwin Lindemann <elindema@wupp. invalidwrote:
            #
            # If a VLA appears within a loop body, it seems the behavior is
            # different with two different compilers I tried. I looked at the
            # standard text, but couldn't find a definite answer there either.

            This is a 48 year old issue. Answer is both block and procedure
            level allocation have their benefits so both will continue to be
            used. Program to cope with either. In particular don't allocate
            arrays in loops unless you're prepared to have the entire amount
            allocated.

            If you must allocate in a loop and you must have it released
            at the end of the loop, put the loop body in a separate function.

            --
            SM Ryan http://www.rawbw.com/~wyrmwif/
            TEMPORARILY CLOSED
            BE OPENED AFTER FIRST PERIOD

            Comment

            • Micah Cowan

              #7
              Re: Variable length arrays

              SM Ryan <wyrmwif@tang o-sierra-oscar-foxtrot-tango.fake.orgw rites:
              Erwin Lindemann <elindema@wupp. invalidwrote:
              #
              # If a VLA appears within a loop body, it seems the behavior is
              # different with two different compilers I tried. I looked at the
              # standard text, but couldn't find a definite answer there either.
              >
              This is a 48 year old issue. Answer is both block and procedure
              level allocation have their benefits so both will continue to be
              used. Program to cope with either. In particular don't allocate
              arrays in loops unless you're prepared to have the entire amount
              allocated.
              Regardless of whether block or procedure-level allocation is used,
              though, there must always be exactly one instance of the object.

              On (non-broken) implementations with block-level allocation, the
              following:

              void foo(int a)
              {
              for (i=0; i!=10000; ++i) {
              int v;
              /* do something with v; */
              }
              }

              would not result in 10,000 "v" objects being simultaneously allocated;
              neither should an "int v[a];" result in such (and the standard
              requires that it does not).

              --
              Micah J. Cowan
              Programmer, musician, typesetting enthusiast, gamer...

              Comment

              • jacob navia

                #8
                Re: Variable length arrays

                Keith Thompson wrote:
                Or perhaps I've misunderstood what's going on here. I don't have
                lcc-win, so I can't test it myself. jacob, can you explain why the
                program dies?
                >
                I replied with a lengthy explanation that you apparently
                did not bother to READ.

                The program dies because for a VLA I do not make the
                optimization that the variable "size" is a loop invariant,
                i.e. does not change within the loop.

                If you replace
                int tab[size];

                with

                int tab[size*i+1];

                gcc will ALSO produce different arrays for each iteration.


                As I explained (and repeat here again) this is an optimization
                that I do not do and gcc does.

                Please read my posts before replying

                thanks

                --
                jacob navia
                jacob at jacob point remcomp point fr
                logiciels/informatique

                Comment

                • Micah Cowan

                  #9
                  Re: Variable length arrays

                  jacob navia <jacob@nospam.c omwrites:
                  Keith Thompson wrote:
                  >Or perhaps I've misunderstood what's going on here. I don't have
                  >lcc-win, so I can't test it myself. jacob, can you explain why the
                  >program dies?
                  >>
                  >
                  I replied with a lengthy explanation that you apparently
                  did not bother to READ.
                  No, you didn't. You explained why new arrays are created, which is
                  fine.. You have failed to explain why the old ones aren't destroyed,
                  as they are required to have been.
                  The program dies because for a VLA I do not make the
                  optimization that the variable "size" is a loop invariant,
                  i.e. does not change within the loop.
                  >
                  If you replace
                  int tab[size];
                  >
                  with
                  >
                  int tab[size*i+1];
                  >
                  gcc will ALSO produce different arrays for each iteration.
                  Sure. Hopefully, though, it will also continue to destroy the old ones
                  first, just as it's required to.

                  --
                  Micah J. Cowan
                  Programmer, musician, typesetting enthusiast, gamer...

                  Comment

                  • Joachim Schmitz

                    #10
                    Re: Variable length arrays

                    jacob navia wrote:
                    Keith Thompson wrote:
                    >Or perhaps I've misunderstood what's going on here. I don't have
                    >lcc-win, so I can't test it myself. jacob, can you explain why the
                    >program dies?
                    >>
                    >
                    I replied with a lengthy explanation that you apparently
                    did not bother to READ.
                    >
                    The program dies because for a VLA I do not make the
                    optimization that the variable "size" is a loop invariant,
                    i.e. does not change within the loop.
                    So you know exactly where the bug in your compiler is and how to fix it.
                    Good.
                    But why then don't you you say so explictly?
                    If you replace
                    int tab[size];
                    >
                    with
                    >
                    int tab[size*i+1];
                    >
                    gcc will ALSO produce different arrays for each iteration.
                    Irrelevant, as others pointed out
                    As I explained (and repeat here again) this is an optimization
                    that I do not do and gcc does.
                    And it doesn't die. This _is_ relevant.
                    Please read my posts before replying
                    Please be more clear in what you want to say.

                    Bye, Jojo


                    Comment

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

                      #11
                      Re: Variable length arrays

                      On Thu, 06 Mar 2008 20:02:22 +0100, jacob navia wrote:
                      If you replace
                      int tab[size];
                      >
                      with
                      >
                      int tab[size*i+1];
                      >
                      gcc will ALSO produce different arrays for each iteration.
                      If you print a pointer to the end of the array, you'll find it has the
                      same address every time. It happens to be a system with a stack that grows
                      downwards, so it's not practical to give the start of the array a fixed
                      location, but there's no reason why the end should not be given one.

                      Comment

                      • jacob navia

                        #12
                        Re: Variable length arrays

                        Micah Cowan wrote:
                        jacob navia <jacob@nospam.c omwrites:
                        >
                        >Keith Thompson wrote:
                        >>Or perhaps I've misunderstood what's going on here. I don't have
                        >>lcc-win, so I can't test it myself. jacob, can you explain why the
                        >>program dies?
                        >>>
                        >I replied with a lengthy explanation that you apparently
                        >did not bother to READ.
                        >
                        No, you didn't. You explained why new arrays are created, which is
                        fine.. You have failed to explain why the old ones aren't destroyed,
                        as they are required to have been.
                        >
                        Required by whom?

                        you?

                        Thompson?



                        --
                        jacob navia
                        jacob at jacob point remcomp point fr
                        logiciels/informatique

                        Comment

                        • Joachim Schmitz

                          #13
                          Re: Variable length arrays

                          jacob navia wrote:
                          Micah Cowan wrote:
                          >jacob navia <jacob@nospam.c omwrites:
                          >>
                          >>Keith Thompson wrote:
                          >>>Or perhaps I've misunderstood what's going on here. I don't have
                          >>>lcc-win, so I can't test it myself. jacob, can you explain why the
                          >>>program dies?
                          >>>>
                          >>I replied with a lengthy explanation that you apparently
                          >>did not bother to READ.
                          >>
                          >No, you didn't. You explained why new arrays are created, which is
                          >fine.. You have failed to explain why the old ones aren't destroyed,
                          >as they are required to have been.
                          >>
                          >
                          Required by whom?
                          >
                          you?
                          >
                          Thompson?
                          common sense?

                          Bye, Jojo


                          Comment

                          • jacob navia

                            #14
                            Re: Variable length arrays

                            Joachim Schmitz wrote:
                            jacob navia wrote:
                            >Keith Thompson wrote:
                            >>Or perhaps I've misunderstood what's going on here. I don't have
                            >>lcc-win, so I can't test it myself. jacob, can you explain why the
                            >>program dies?
                            >>>
                            >I replied with a lengthy explanation that you apparently
                            >did not bother to READ.
                            >>
                            >The program dies because for a VLA I do not make the
                            >optimization that the variable "size" is a loop invariant,
                            >i.e. does not change within the loop.
                            So you know exactly where the bug in your compiler is and how to fix it.
                            Good.
                            But why then don't you you say so explictly?
                            >
                            because there is no bug./

                            Nowhere in the standard it is written that I must free those
                            arrays
                            >If you replace
                            >int tab[size];
                            >>
                            >with
                            >>
                            >int tab[size*i+1];
                            >>
                            >gcc will ALSO produce different arrays for each iteration.
                            Irrelevant, as others pointed out
                            >
                            >As I explained (and repeat here again) this is an optimization
                            >that I do not do and gcc does.
                            And it doesn't die. This _is_ relevant.
                            not to me

                            The standard does not specify that those arrays should be destroyed.
                            They are no longer available, that's all.


                            --
                            jacob navia
                            jacob at jacob point remcomp point fr
                            logiciels/informatique

                            Comment

                            • Joachim Schmitz

                              #15
                              Re: Variable length arrays

                              jacob navia wrote:
                              Joachim Schmitz wrote:
                              >jacob navia wrote:
                              >>Keith Thompson wrote:
                              >>>Or perhaps I've misunderstood what's going on here. I don't have
                              >>>lcc-win, so I can't test it myself. jacob, can you explain why the
                              >>>program dies?
                              >>>>
                              >>I replied with a lengthy explanation that you apparently
                              >>did not bother to READ.
                              >>>
                              >>The program dies because for a VLA I do not make the
                              >>optimizatio n that the variable "size" is a loop invariant,
                              >>i.e. does not change within the loop.
                              >So you know exactly where the bug in your compiler is and how to fix
                              >it. Good.
                              >But why then don't you you say so explictly?
                              >>
                              >
                              because there is no bug./
                              OK, see how unclear your wording was?
                              Nowhere in the standard it is written that I must free those
                              arrays
                              And what does common sense say? Isn't it you how constantly wants to improve
                              the standard?
                              >>If you replace
                              >>int tab[size];
                              >>>
                              >>with
                              >>>
                              >>int tab[size*i+1];
                              >>>
                              >>gcc will ALSO produce different arrays for each iteration.
                              >Irrelevant, as others pointed out
                              >>
                              >>As I explained (and repeat here again) this is an optimization
                              >>that I do not do and gcc does.
                              >And it doesn't die. This _is_ relevant.
                              >
                              not to me
                              >
                              The standard does not specify that those arrays should be destroyed.
                              They are no longer available, that's all.
                              Even if it's not required by a standard, this is a Quality Of Implemenation
                              issue.
                              Destroying those arrays would surely not violate the standard, would it?
                              And I'd find such a "feature" much more usefull than a printf format
                              specified for complex numbers...

                              Bye, Jojo


                              Comment

                              Working...