在要释放的块内调用 Block_Release

Call Block_Release inside block to be released

是否可以在自身内部释放一个方块?对于编译器来说没问题,但我不确定在运行时它是否会崩溃,因为它会释放同时执行的内存。

cancel_block_t someFunction(/*args*/){
    __block BOOL canceled = NO;
    __block cancel_block_t cancel_block = Block_copy(^{
        canceled = YES;
        Block_Release(cancel_block); //<-- can I do this?
        cancel_block = NULL; //<-- can I do this?
    });
    // […]
    return cancel_block;
}

这种方法会更安全吗?

 cancel_block_t someFunction(/*args*/){
    __block BOOL canceled = NO;
    __block cancel_block_t cancel_block = Block_copy(^{
        canceled = YES;
        dispatch_async(dispatch_time(DISPATCH_TIME_NOW, 0.001 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),^{
            Block_Release(cancel_block);
            cancel_block = NULL;
        });
    });
    // […]
    return cancel_block;
}

感谢您的帮助!

编辑 #1:更正了 return 函数类型。

这是非ARC代码吗? ARC 将自动复制、保留和释放块。

无论如何,这并不安全,至少并非总是如此。我见过类似行为的崩溃。问题是对 __block 变量的引用在 Block_release() 可能解除分配的同一个块对象中。因此,尝试设置变量可以在它被释放(并且可能被重用)后访问内存。

关于你的职能:

1) 为什么它 return 是一个指向块类型的指针?该函数仅 return 块类型(已经是引用)会更正常。也就是说,someFunction() 应该有一个 return 类型的 cancel_block_t,而不是 cancel_block_t*。无论如何,获取 __block 变量的地址是不安全的,因为这样的变量可以改变位置。它在堆栈上开始生命,但被移动到堆上。

2) return 块的函数的正常语义是 return 自动释放的对象。所以,someFunction() 应该只是 return [cancel_block autorelease];(假设它已经被复制)。如果调用者想要将其保留在当前范围或自动释放池之外,则有责任保留它。如果它被提交给一个函数(例如 dispatch_async()),那么该函数负责保留它。换句话说,内存管理语义与任何其他对象相同。该块不应尝试自行释放。