我正在尝试调试在支持 A64 instruction set 的设备上一致重现的 iOS 崩溃.特别是使用 A7 的 iPad/A8X SoC的。在任何 32 位 iPad 上运行时,完全相同的代码也始终不会崩溃(如果我将构建限制为仅 32 位架构,然后在 iPad 上运行 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_msgSend 和 performSelector:withObject: 在这种情况下应该基本上是等价的。
那么为什么一个崩溃(并且仅在使用 A64 时)而另一个不崩溃?
下一个令人费解的事情是在崩溃发生时尝试对其进行调试。 self 和 object 都是 NSManagedObject 实例,我可以在调试器中观察到它们都是有效对象。但是,异常总是报告为:
-[NSManagedObjectContext 实体]:无法识别的选择器发送到实例 0x...
调用显示为源自 CoreData 的内部结构,我无法想出任何合理的解释来说明这是如何发生的,尤其是从32 位到 64 位架构/构建。
对于导致此类问题的原因有什么想法吗?或者我应该只使用 performSelector:withObject: 并开心吗?
最佳答案
and there's nothing particularly fancy about the code that triggers it
正如您所发现的,直接调用 objc_msgSend() 很花哨,而且很难正确执行。
The first perplexing part is that if I replace this line with [self performSelector:addSelector withObject:object];, everything works as it should
是的。因为这些不一样。
objc_msgSend* 有多种风格,您需要根据返回类型和您的处理器选择正确的一种。具体分为三个版本:
objc_msgSend_fpret -- 对于浮点返回类型(适用于 OS X;我还没有查过它是否适用于 64 位 ARM)objc_msgSend_stret -- 对于结构返回类型(如 CGPoint)objc_msgSend -- 对于其他返回类型如果这在所有处理器上总是完全正确,我想不起来了。一些处理器对待“大”结构的方式与对待“小”结构的方式不同。调用约定都是特定于处理器的,这就是为什么你只在一个处理器上看到它。还记得我说过直接调用 objc_msgSend() 很花哨吗?
您使用它来调用任意选择器的事实表明它们中的一些具有结构或浮点返回值,在这种情况下,事情会在错误的寄存器中并且事情会完全横向。
有关这方面的更多讨论,请参阅 Why does the Objective-C compiler need to know method signatures? .
Are there any ideas on what would cause this kind of issue? Or should I just go with that performSelector:withObject: and be happy?
正如警告所说,performSelector: 可能会泄漏,因为 ARC 不知道如何对其进行内存管理。解决方案是修改它以使用 block 而不是选择器。如果您必须使用选择器,并且您确定此处调用的选择器都不会返回对象,请参阅 https://stackoverflow.com/a/7933931/97337如何消除警告。如果这些可以返回对象,那么你需要确保它们不能有额外的保留,这只是一个你可能不应该去的兔子洞(或者至少应该作为一个新问题来问)。
关于ios - A64 : objc_msgSend crashes while performSelector:withObject: works,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30218810/