alloca() is not a standard C primitive. It's only an extension, and its purpose is to dynamically allocate memory that is automatically freed. Using a dynamic amount of stack space is dynamic allocation, it's just not on the heap.
This still makes it really easy to overflow your stack, especially if for example your loop count above can come from user input. This is dangerous for all the same reasons that variable-length arrays are dangerous.
The proposal poses object value capture as an open question. See heading "Should object values be captured?" on page 14 of the proposal: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2542.pdf
Yes, you are correct and there wasn't much support for capturing values so we would probably only support capture by reference and wait to see if C solves this problem in general by introducing lambdas.
So I expect the implementation would be
1. If a defer block references variables which do not live to the end of the guard block, the program is malformed (compiler error).
2. Compile each defer block as if it was written at the end of the guard block. What order the defer blocks are stored in is implementation-defined
3. Put a pointer on the stack each time a defer statement executes pointing to the compiled defer statement.
With this each defer statement is just a few bytes of overhead added to the stack and you can do it in a loop, though it may not do what you expect if you come from Go. For the example I expect the compiler to emit code similar to:
This makes defer more or less just a mechanical transformation of code that can be expressed with existing C primitives and without requiring dynamic memory. I think it would be a good addition to C's structured programming elements.