我遇到了一个问题,我的iOS应用程序在退出时崩溃了,我将其缩小到这个范围:
// File.h
struct Name {
NSString *name;
}
// File.mm
Name names[] = {
@"foo",
@"bar",
};
当应用程序退出时(按下iPad上的主页按钮),objc_msgSend
的{{1}}崩溃了。它正在发生在析构函数EXC_BAD_ACCESS (SIGSEGV)
。
Name::~Name()
请记住,这是在.mm文件中,所以它被编译为obj-c ++。
这已经好几个月了。我不确切知道它何时开始发生,但我怀疑是在我更新到xcode 4.4时。
0 libobjc.A.dylib 0x37586e3a objc_release + 10
1 MyApp 0x0014abfc Name::~Name() (NameManager.h:21)
2 MyApp 0x0014ab42 Name::~Name() (NameManager.h:21)
3 MyApp 0x0014ad94 __cxx_global_array_dtor + 120
4 libsystem_c.dylib 0x36bba1cc __cxa_finalize + 216
5 libsystem_c.dylib 0x36b854f6 exit + 6
文字应该受到多个版本的保护(或者一直都是),但我认为无论如何都不会发生这种情况。
有人知道xcode 4.4中有什么变化吗?
我可以通过执行以下操作来修复崩溃:
NSString
但是我讨厌这样做而不理解为什么之前有效的东西不再起作用。或许它永远不应该有效。我也担心内存覆盖过多,所以这可能只是一种症状。
在DEBUG和RELEASE中都会发生这种情况。
更新:我在~Name()中放了一个断点,并验证内存没有损坏。 LLDB能够转储NSString OK。但是当我走的时候它会崩溃。
答案 0 :(得分:1)
当您在Objective-C ++中声明包含启用了ARC的Objective-C对象的“普通旧数据”struct
时,编译器有义务提供一个析构函数,该析构函数正确释放结构的ObjC成员,即使你自己不写。
此限制不适用于Objective-C ++。然而,非常重要 所有权限定类型被认为是非POD:在C ++ 11术语中,它们 不是简单的默认可构造,复制可构造,移动 可构造的,可复制的,可移动的可分配的或可破坏的。它 是违反C ++的一个定义规则来使用外面的类 在ARC下,ARC将具有非常重要的所有权限制 构件。
当您声明Name结构时,编译器会为您编写一个涉及隐式强保持Objective-C对象的析构函数。在执行时,这意味着C ++析构函数会删除它所期望的C ++结构,而是将指针串起来。如果没有有效的指针,-release
ARC会在尝试取消引用不存在的接收器时尝试发送段错误。
当你声明一个Objective-C成员__unsafe_unretained
时,它告诉ARC将它从它必须编写的析构函数中排除,因此结构只是被销毁,而-release
永远不会被发送。建议您将结构或类中的所有Objective-C对象标记为__unsafe_unretained
,并自行提供适当的内存管理,因为ARC可以使跨语言的对象生命周期复杂化。