在Block内使用__block修饰的C++类变量触发_Block_copy崩溃如何解决
问题根因
- 语法疏漏:
__block MyClass obj(a1 c1);两个构造参数间遗漏了逗号,应为__block MyClass obj(a1, c1);,该问题会导致编译失败,不是运行时崩溃的直接原因。 - 核心崩溃原因:
- 你显式删除了
MyClass的左值拷贝构造函数,仅保留了移动构造函数。当你用__block修饰栈上的MyClass对象时,dispatch_async的内层Block会被拷贝到堆区,系统在拷贝__block修饰的C++对象时会默认尝试调用拷贝构造函数,拷贝构造被删除后对象无法正确拷贝,触发_Block_copy内部的内存操作崩溃。 __block语义本身是用于支持在Block内部修改外部栈变量,你当前场景仅需要将对象传递到异步Block中使用,使用__block属于不必要的错误用法,额外引入了对象拷贝的风险。
- 你显式删除了
修复方案
方案1:堆上分配对象,用智能指针管理(兼容性最好)
将MyClass放到堆上,用智能指针持有,避免C++对象直接被Block拷贝:
#include <memory> my_processor = ^(int* c1, const int* a1){ std::shared_ptr<MyClass> obj = std::make_shared<MyClass>(a1, c1); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { ProcessMyData(*obj); }); };
如果不需要多持有者,也可以用std::unique_ptr配合移动语义传入Block。
方案2:移除__block修饰,用移动语义转移对象所有权
不需要__block修饰,直接将对象移动到异步Block中,触发你已经实现的移动构造函数,避免拷贝:
my_processor = ^(int* c1, const int* a1){ MyClass obj(a1, c1); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { ProcessMyData(std::move(obj)); }); };
该方案要求你当前编译环境开启了C++11及以上的语言标准。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

