A64: objc_msgSend crashes while performSelector:withObject:



我正在尝试对iOS进行调试,该iOS在支持A64指令集的设备上持续再现。特别是使用A7/A8X SOC的iPad。在任何32位iPad上运行时,完全相同的代码也将始终崩溃(如果我将构建仅限于32位体系结构,则适用于相同的情况,然后在一个上运行32位代码64位具有iPad)。

崩溃报告为EXC_BAD_ACCESS,并且对触发它的代码没有什么特别的幻想:

if (object && [self respondsToSelector:addSelector]) {
    objc_msgSend(self, addSelector, object);                  //EXC_BAD_ACCESS on A64 devices!
    //[self performSelector:addSelector withObject:object];   //no crash  
}

有问题的行是objc_msgSend(self, addSelector, object);。第一个令人困惑的部分是,如果我用[self performSelector:addSelector withObject:object];替换这条线,一切都应该奏效(尽管它使我感到令人讨厌的" PerformSelector可能会导致泄漏..."警告)。除非我完全误解了某些内容,否则在这种情况下,objc_msgSendperformSelector:withObject:本质上应等效。

那么,为什么一个一个崩溃(仅在使用A64时)而另一个不使用?

下一个令人困惑的事情是在试图在发生崩溃时调试崩溃时会发生的。selfobject都是NSManagedObject实例,我可以在调试器中观察到它们都是有效的对象。但是,该例外总是报告为:

-[NSManagedObjectContext entity]: unrecognized selector sent to instance 0x...

该呼叫显示为源自CoreData的内部设备,我无法提出任何可能发生的情况的合理解释,尤其是作为切换到32位转换为64--的副作用位体系结构/构建。

有什么想法会导致这种问题?还是我应该选择那个performSelector:withObject:并开心?

,触发它的代码没有什么特别的幻想

直接调用 objc_msgSend() fancy,并且在发现时正确地做到了。

第一个令人困惑的部分是,如果我用[self performelector:addSelector with obobject:object]; extery exterector

替换此行

是的。因为这些不一样。

objc_msgSend*有几种口味,您需要根据返回类型和处理器选择正确的口味。具体来说,有三个版本:

  • objc_msgSend_fpret-对于浮点返回类型(适用于OS X;我没有查找它是否适用于64位臂)
  • objc_msgSend_stret-对于结构返回类型(例如CGPoint
  • objc_msgSend-对于其他返回类型

如果在所有处理器上总是始终是 true,我不记得我的头顶。一些处理器对"大"结构的处理方式不同于"小"结构。呼叫约定都是非常特定于处理器的,这就是为什么您只在一个处理器上看到它的原因。还记得我说直接打电话objc_msgSend()时很喜欢吗?

您正在使用它来调用任意选择器的事实表明,其中一些人具有结构或浮点返回,在这种情况下,事物将在错误的寄存器中,并且事情将完全侧面进行。p>有关此此讨论的更多讨论,请参阅为什么Objective-C编译器需要了解方法签名?

有什么想法会导致这种问题?还是我应该选择那个performelector:withObject:快乐?

正如警告所述,performSelector:可能会泄漏,因为ARC不知道如何进行内存来管理它。解决方案是对此进行重新处理以使用块而不是选择器。如果您必须使用选择器,并且可以肯定地知道,此处都没有调用返回对象的选择器,请参见https://stackoverflow.com/a/7933931/97337有关如何使警告保持沉默。如果这些可以返回对象,那么您需要确保在它们上不能有额外的保留,这只是您可能不应该下降的兔子洞(或至少应该作为一个新问题提出)。

最新更新