4

Okay, so apparently this works:

void foo(size_t s) {
    int myArray[s];
    // ... use myArray...
}

Is this really legal? I mean, it must be, because it compiles (where the C compiler would reject it as non-constant). The first part of my question is: how does this work? I assume it's allocating it on the stack? Is this different from using alloca()?

Practically, I found some code that does this:

void bar(size_t chunkSize) {
    CFReadStreamRef foo = NULL;
    // ...some stuff to init foo...

    while (stuffToDo) {
        UInt8 buffer[chunkSize];
        // ...read some data from stream into buffer
        //    using CFReadStreamRead()...
    }
}

This works. However, when I move the buffer allocation from inside the loop to the first line of the function (directly before foo is declared), the function... stops working. In the debugger it gets to the first access of local variables and then just... exits. I don't see any exceptions being thrown, it doesn't crash, it just program carries on running (in reality the function returns a string and that return value is NULL, which is what the return variable is initialized to). I'm not sure what's going on. The second part of my questions is, in light of the first part, what the heck is going on?

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222

1 Answers1

3

it is legal in C99, although dangerous, and yes -- it is like alloca.

because it's like alloca, you want reasonably sized arrays when allocating on the stack. i am not sure if this is defined if the length is zero, but you could definitely cause a stack overflow if the array is 'large enough' to do so.

as far as what is going on -- pulling it out of the loop should make no difference if the sizes are reasonable. i suspect you are seeing undefined behavior because a parameter value is too large (or perhaps 0) -- you should validate the chunkSize parameter. the assembly will tell you why pulling it out of the loop makes a difference (assuming everything else in the program is well-formed).

justin
  • 104,054
  • 14
  • 179
  • 226
  • Clearly. And I found some sources saying it's dangerous, and clearly it is. But I'd like to understand how it's dangerous and how to correctly use it. – i_am_jorf Aug 10 '12 at 19:41
  • 1
    @jeffamaphone: Because `char foo[some_large_value]` may very well blow your stack. There is really no good reason for this feature to exist. – Ed S. Aug 10 '12 at 19:43
  • @EdS. agreed, i avoid using this feature. – justin Aug 10 '12 at 19:48
  • Yes... the code had all sorts of problems and I'm fixing it. Among other bad things, we will no longer be doing this either. But I wanted to understand why / how it worked first. – i_am_jorf Aug 10 '12 at 19:50
  • @jeffamaphone ok - i also added a bit regarding the second half of your post. – justin Aug 10 '12 at 19:55