Блокировать жизненный цикл в функции? - PullRequest
1 голос
/ 16 января 2012

Блочная переменная в target-c является ссылкой, и я откуда-то узнал, что следующий код может быть преобразован компилятором в другую форму.

Исходный код:

typedef int (^block_type)();
block_type create_k(int i)
{
    block_type block = ^(){
        return i;
    };
    //[block copy];
    return block;
}

Сгенерированный код:

typedef void (*generic_invoke_funcptr)(void *, ...);
struct __block_literal {
    void *isa;
    int flags;
    int reserved;
    generic_invoke_funcptr invoke;
    struct __block_descriptor_tmp *descriptor;
    const int captured_i;
};
static const struct __block_descriptor_tmp {
    unsigned long reserved;
    unsigned long literal_size;
    /* no copy/dispose helpers needed */
} __block_descriptor_tmp = {
    0UL, sizeof(struct __block_literal)
};
// ^int (void) { return i; }
int __create_k_block_invoke_(struct __block_literal *bp) {
    return bp->captured_i;
}
typedef int (*iv_funcptr)(struct __block_literal *);

typedef int (^block_type)();
block_type create_k(int i)
{

    //block_type block = ^(){
    //    return i;
    //};
    struct __block_literal __b = {
        .isa = &_NSConcreteStackBlock,
        .flags = BLOCK_HAS_DESCRIPTOR,
        .reserved = 0,
        .invoke = (generic_invoke_funcptr)__f_block_invoke_,
        .descriptor = &__block_descriptor_tmp,
        .captured_i = i
    };
    struct __block_literal *block = &__b;
    return block;
}

Итак | _ b |в стеке и блоке является только ссылкой на | _b |.Если | создать_k |return | block |, получатель получит только неверный адрес.

Но

 int main(int argc, const char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    printf("%d\n", create_k(40)());
    [pool drain];
    return 0;
}

Выполнив его, выведите | 40 |и | блок |является действительным блоком.В чем дело?

1 Ответ

1 голос
/ 16 января 2012

Я думаю, что память для этого стекового фрейма еще не обнулена. Попробуйте вызвать другую функцию между create_k () и printf (), чтобы получить там другие случайные данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...