是否有可能在其内部释放一个块?对于编译器来说没问题,但是我不确定它是否会在运行时崩溃,因为它释放了同时执行的内存。
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:更正了函数的返回类型。
答案 0 :(得分:1)
这是非ARC代码吗? ARC将自动复制,保留和释放块。
无论如何,这不安全,至少并非总是如此。我已经看到类似行为的崩溃。问题是对__block
变量的引用位于Block_release()
可能解除分配的同一块对象中。因此,尝试设置变量可以在释放(并且可能重用)后访问内存。
关于你的功能:
1)为什么它返回指向块类型的指针?函数返回块类型(已经是引用)更为正常。也就是说,someFunction()
的返回类型应为cancel_block_t
,而不是cancel_block_t*
。无论如何,获取__block
变量的地址是不安全的,因为这样的变量可以改变位置。它从堆栈开始,然后移动到堆中。
2)返回块的函数的正常语义是返回一个自动释放的对象。因此,someFunction()
应该只是return [cancel_block autorelease];
(因为它已被复制)。如果调用者想要将其保留在当前范围或自动释放池之外,则负责保留它。如果它已提交给函数(例如dispatch_async()
),则该函数负责保留它。换句话说,内存管理语义与任何其他对象相同。该块不应该试图释放自己。