Xcode开启Zombie Objects(僵尸对象)检测EXC_BAD_ACCESS
Xcode开启Zombie Objects(僵尸对象)检测EXC_BAD_ACCESS

Xcode开启Zombie Objects(僵尸对象)检测EXC_BAD_ACCESS

什么是 Zombie Objects?

当开启 “Zombie Objects” 后,对象不会立即释放,而是会被转成特殊的 “NSZombie” 类型。这样,当错误地访问这个已释放对象时,不会直接崩溃,而是输出更清晰的调试信息,比如:

-[MyClass doSomething]: message sent to deallocated instance 0x123456

这比原始的报错信息:

Thread 3: EXC_BAD_ACCESS (code=2, address=0x...)

要清晰很多。

开启Zombie Objects

1、打开Xcode项目。

2、点顶部菜单:Product > Scheme > Edit Scheme。

3、在左侧选中Run(运行目标)。

4、点击 Diagnostics。

5、勾选 Memory Management – Zombie Objects选项。

运行程序

开启Zombie Objects后,运行发生EXC_BAD_ACCESS的程序,Xcode控制台会输出:

*** -[MyClass doSomething]: message sent to deallocated instance 0x123abc

还可以同时启用以下选项:

1、Malloc Scribble:释放内存时填充 0xAA,帮你更早发现非法使用。

2、Malloc Guard Edges:在 malloc 分配两端放 guard 区域,用于发现越界读写。

3、Malloc Stack Logging:记录 malloc 调用栈,用 Instruments 查看谁分配的内存。

这些工具组合起来,对付内存问题非常高效。

注意事项

性能下降:调试用,别在发布版本开启。

内存占用会变高:僵尸对象不会释放,适合定位问题,而不是持续使用。

常用问题场景

1、delegate 没设置为 weak。

2、对象释放后仍访问。

3、捕获循环或异步访问错误引用。

4、Combine、GCD、async/await 捕获了生命周期错误对象。

总结

Zombie Objects(僵尸对象)可以检测EXC_BAD_ACCESS的崩溃问题,并输出详细的信息。

对于无法通过Zombie Objects检测的崩溃,可以尝试使用Task { @MainActor in }包裹崩溃的代码字段:

Task { @MainActor in
    // 代码行
}

因为某些对象的生命周期或线程访问不安全,违反了线程要求,也是造成EXC_BAD_ACCESS的崩溃原因。

扩展知识

无法捕获崩溃的问题

如果开启Zombie Objects后,仍然出现EXC_BAD_ACCESS 并没有显示类似:

*** -[MyClass method]: message sent to deallocated instance 0x...

说明,这个崩溃不是由于「消息发送给已释放对象(Zombie)」引起的,而是属于以下几种情况之一:

一、C/C++ 层级或 CoreFoundation 层级的内存访问(无法被 Zombie 捕捉)

Zombie 机制只对 Objective-C 对象的方法调用生效。

如果崩溃发生在:

1)CoreFoundation (CFArray、CFUUID 等);

2)CoreGraphics、CoreMedia、AVFoundation 等底层 C-API;

3)使用了 C 指针(如 UnsafeMutablePointer)访问内存;

4)Metal 或某些底层系统库返回已释放对象;

那 Zombie 就无法catch 到具体对象或类型。

二、非消息调用(即不是调用 [obj method])引起的访问

比如直接访问了已释放对象的内存地址或成员变量,而不是通过方法发送消息,也不会被 Zombie 捕捉:

let name = someObject.name // 直接访问属性

如果 someObject 已释放,这也只会触发 EXC_BAD_ACCESS,Zombie 不会输出任何信息。

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注