gpt4 book ai didi

objective-c - 调试过度释放的对象,NSZombie 的问题

转载 作者:太空狗 更新时间:2023-10-30 03:56:50 25 4
gpt4 key购买 nike

编辑:我找到了这次崩溃的原因! bbum 指出缓冲区溢出是一个很常见的原因,所以我查看了我拥有的唯一缓冲区类型 malloc:

closedList = (AINavigationCell **)malloc(baseCells.count * sizeof(AINavigationCell *));

我后来覆盖了超出数组边界的数据,它应该比 baseCells.count 大得多。谢谢你!

问题:我在 NSAutoreleasePool 期间有一个可重现的 EXC_BAD_ACCESS -drain,这似乎表明我过度释放了一个对象。所以我启用了 NSZombie,但是程序不再崩溃了。我也没有将任何信息记录到控制台。如果我关闭 NSZombie,崩溃又回来了。这是什么意思?我认为 NSZombies 正是用来解决这类问题的。如果 NSZombie 无济于事,是否有另一种方法来审问这个过度释放的对象?

此外,崩溃无法在模拟器上重现,这就是我不能将 Instruments 与 NSZombie 一起使用的原因。

以下是崩溃点的回溯。

#0  0x31ac8bc8 in _cache_fill ()
#1 0x31acaf8e in lookUpMethod ()
#2 0x31ac8780 in _class_lookupMethodAndLoadCache ()
#3 0x31ac859a in objc_msgSendSuper_uncached ()
#4 0x328014f0 in -[__NSArrayReverseEnumerator dealloc] ()
#5 0x327b1f7a in -[NSObject(NSObject) release] ()
#6 0x327b63c8 in CFRelease ()
#7 0x327b58de in _CFAutoreleasePoolPop ()
#8 0x320e132c in NSPopAutoreleasePool ()
#9 0x30899048 in CAPopAutoreleasePool ()
#10 0x30902784 in CA::Display::DisplayLink::dispatch ()
#11 0x309027ea in CA::Display::IOMFBDisplayLink::callback ()
#12 0x30076bfa in IOMobileFramebufferVsyncNotifyFunc ()
#13 0x333dee6a in IODispatchCalloutFromCFMessage ()
#14 0x327e8be6 in __CFMachPortPerform ()
#15 0x327e06fe in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#16 0x327e06c2 in __CFRunLoopDoSource1 ()
#17 0x327d2f7c in __CFRunLoopRun ()
#18 0x327d2c86 in CFRunLoopRunSpecific ()
#19 0x327d2b8e in CFRunLoopRunInMode ()
#20 0x3094a4aa in GSEventRunModal ()
#21 0x3094a556 in GSEventRun ()
#22 0x32c14328 in -[UIApplication _run] ()
#23 0x32c11e92 in UIApplicationMain ()
#24 0x00002556 in main (argc=1, argv=0x2fdff660) at /Users/hyn/Desktop/MyProject-trunk/main.m:14

最佳答案

您描述的问题可能是以下几个问题之一;您可能过度释放了一个对象,或者您可能正在破坏内存。如果您破坏了内存——特别是破坏了对象的前几个字节——那么它很容易在自动释放池耗尽(或任何其他消息)期间表现为崩溃。

崩溃发生在设备上,而不是模拟器上,这也表明内存损坏。设备 [ARM] 与模拟器 [i386] 的架构完全不同,可能存在许多问题。

通常,它不会始终如一地表现出来。

首先,发布崩溃的回溯。这可能会有所帮助。

其次,您是否执行任何类型的原始 malloc 调用?或者用数据填充缓冲区?此类崩溃的最常见原因是运行超过了缓冲区的末尾。


#0  0x31ac8bc8 in _cache_fill ()
#1 0x31acaf8e in lookUpMethod ()
#2 0x31ac8780 in _class_lookupMethodAndLoadCache ()
#3 0x31ac859a in objc_msgSendSuper_uncached ()
#4 0x328014f0 in -[__NSArrayReverseEnumerator dealloc] ()

(以上内容是在 OP 修复问题后添加的,但是——用于存档)

那个崩溃痕迹是内存损坏的经典特征。也就是说,isa 指针——指向实例类的对象中第一个指针的字节值——被踩踏了。当您在对象分配 之前溢出内存缓冲区时,通常会发生这种情况。如果它只是几个字节溢出,那么不同平台之间的行为可能会有所不同,因为 malloc 量子 - 分配的实际大小(你在一个平台上要求 90 个字节,你可能会得到 96。另一个?128) - - 不同平台,甚至不同版本。

特别是,isa 被一个看起来很像指针的值踩踏,运行时取消引用垃圾值,然后尝试将结果位置视为类的方法表。

任何时候你看到一个深度为 objc_msgSend*() 函数之一的崩溃,很可能是内存损坏,如果是这样,它几乎总是一个缓冲区溢出。

因为这很容易做到,所以通过僵尸检测来进行测试以捕捉“有时它真的只是过度释放的情况”仍然是一个好主意。

关于objective-c - 调试过度释放的对象,NSZombie 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4848137/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com