C w / Blocks: stack-based blocks coming out of scope

In one of Apple's header files for libdispatch , queue.h , the following warning appears:

 // The declaration of a block allocates storage on the stack. // Therefore, this is an invalid construct: dispatch_block_t block; if (x) { block = ^{ printf("true\n"); }; } else { block = ^{ printf("false\n"); }; } block(); // unsafe!!! // What is happening behind the scenes: if (x) { struct Block __tmp_1 = ...; // setup details block = &__tmp_1; } else { struct Block __tmp_2 = ...; // setup details block = &__tmp_2; } // As the example demonstrates, the address of a stack variable is // escaping the scope in which it is allocated. That is a classic C bug. 

Try it as I can, I can’t come up with a test case illustrating this error. I can create blocks that are created on the stack, but they (seem to) always appear at unique addresses on the stack, even if they are inaccessible to each other.

I guess the answer to this question is simple, but it eludes me. Can someone fill in the blanks in my (limited) understanding?

EDIT : I saw this answer, but I don’t quite understand how this instance can translate to my example published above. Can someone show me an example using if constructs?

+8
c objective-c-blocks grand-central-dispatch
source share
1 answer

To hide the stack closure inside a function:

  • You need to make sure that closing is indeed a stack closing. With Apple Clang 2.1, a closure that does not reference variables in its current context (for example, in queue.h) is implemented as a global closure. This is an implementation detail that may vary across compiler / compiler versions;

  • The compiler should emit code that effectively reuses / overwrites the area of ​​the stack where it was once closed. Otherwise, each object inside this function lives in a different address in the frame of the function stack, which means that you will not get a failure inside this function. It seems that Apple Clang 2.1 does not use stack memory addresses. GCC 4.6 can reuse them, but it does not support closure.

Since Apple Clang 2.1 does not reuse addresses in the frame of the function stack, and GCC 4.6 does not support closing, from what I can say that it is impossible to do this in this particular example - inside the function cause the stack to close due to crash.

I wrote a more detailed text about this on my blog .

+5
source share

All Articles