EXC_BAD_ACCESS但NSZombies从未触发,如何调试?

时间:2018-03-31 01:27:00

标签: ios objective-c xcode exc-bad-access

我们发生了一些非常随机的错误并抛出EXC_BAD_ACCESSmalloc_error_breakabor t。异常没有一致性,启用NSZombies不会导致任何僵尸被触发。

事实上,在启用僵尸的情况下运行会导致崩溃永远不会发生。我相信这个代码库中存在一个微妙的内存错误,并且在花了很多时间清理可能是小问题之后,我们仍然没有解决问题。

错误的指针可能会覆盖一块内存,然后解除引用并崩溃应用程序。但是,有哪些其他方法可以隔离潜在的问题?

我们已经使用了所有附带设备运行的诊断内存工具(此应用程序使用外围设备,因此无法在模拟器中完全调试)。

1 个答案:

答案 0 :(得分:2)

NSZombie只是一种毒害对象使用空间而不是释放它们的机制,类似于Address Sanitizer's Memory Poisoning。通过使用诸如NSZombie或上述ASAN之类的各种检测,您的堆栈和堆分配将以不同的方式布局,导致在崩溃可能是最佳情况的情况下的未定义行为。

EXC_BAD_ACCESS表示您尝试访问无效地址或尝试读取或写入您没有此类权限的内存区域。您遇到的不一致可能是令人讨厌的堆栈或堆损坏的后果,例如有时会覆盖只保存数据的变量,有时会覆盖程序使用的指针。

数据布局对于发生的事情非常重要,并且堆布局通常在非调试版本中随机化,这为不一致的崩溃增加了更多空间。此外,对程序源代码或构建设置的任何更改都可能/将不可避免地导致数据布局更改。

我建议:

  1. 构建调试模式(-g编译器标志)并运行附加的调试器。当您遇到崩溃时,gdblldb(后者是Xcode工具的默认设置)将停止执行并让您执行操作,从那里使用bt获取堆栈跟踪可能会让你解决问题的深层原因。
  2. 使用ASAN,this page explains about its usage within Xcode tooling。它通常是处理内存问题的绝佳工具。请注意,将其与不支持它的共享库一起使用可能会导致异常,但它通常会告诉您它们并且通常会尽可能多地握住您的手。
  3. “printf debugging”可以提供帮助,比如#define TRACE printf("%s %s:%d\n", __func__, __FILE__, __LINE__);,并将这些问题分散到可能的问题点实际上可能会有所帮助。
  4. 一般情况下,我建议首先使用调试器,不使用NSZombie或其他任何东西,只需执行一系列运行即可发生崩溃并获取堆栈跟踪,注册状态等。将这些样本跨多个崩溃可以帮助您缩小问题范围。