开发者

C w/ Blocks: Stack-based blocks going 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 as I may, I cannot come up with a test case that exemplifies this bug. I can create blocks that are instantiated on the stack, but they (seem to) always appear at unique addresses on the stack, even when out of scope with respect to each other.

I imagine that the answer to this is simple, but it escapes me. Can anyone fill the gaps in my 开发者_开发知识库(limited) understanding?

EDIT: I've seen this response, but I don't quite understand how that instance can translate to my example posted above. Can someone show me an example using if constructs?


In order to crash a stack closure inside a function:

  • You need to make sure that the closure is indeed a stack closure. As of Apple Clang 2.1, a closure that doesn’t reference variables in its current context (like the one in queue.h) is realised as a global closure. This is an implementation detail that can vary amongst different compilers/compiler versions;

  • The compiler must emit code that effectively reuses/rewrites the stack area where the closure once lived. Otherwise, every object inside that function lives in a different address in the function stack frame, which means you won’t get a crash inside that function. It seems that Apple Clang 2.1 doesn’t reuse stack memory addresses. GCC 4.6 can reuse them, but it doesn’t support closures.

Since Apple Clang 2.1 doesn’t reuse addresses in a function stack frame and GCC 4.6 doesn’t support closures, from what I can tell it’s not possible to make this particular example — inside a function, invoke an out of scope stack closure — crash.

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜