2015-05-13 42 views
2

我試圖調試iOS上的崩潰,在支持A64 instruction set的設備上一致地重現。特別是使用SoC的A7/A8X的iPad。在任何32位iPad上運行時,完全相同的代碼也會一致而不是崩潰(如果我將構建限制爲只有32位體系結構,然後在具有64位功能的iPad上運行32位代碼)。A64:objc_msg發送崩潰,而performSelector:withObject:工作

的崩潰報告爲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:,並開心?

+0

你使用的SQLite數據庫類型? –

+0

@WarrenBurton - 是的,應用程序在CoreData中使用'NSSQLiteStoreType'。 – aroth

+0

什麼是addSelector? –

回答

2

,並沒有什麼特別花哨的關於觸發它

調用objc_msgSend()直接代碼看中,並棘手正確地做,因爲你發現。

第一部分令人費解的是,如果我替換[自performSelector:addSelector withObject:對象]這條線;,一切工作,因爲它應該

是啊。因爲這些不一樣。

有幾種風味的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?

有什麼想法會導致這種問題?或者我應該去那個performSelector:withObject:並開心?

由於警告說,performSelector:可能泄漏,因爲ARC不知道如何進行內存管理它。解決方法是重新使用塊而不是選擇器。如果您必須使用選擇器,並且您肯定知道這裏調用的選擇器沒有返回對象,請參閱https://stackoverflow.com/a/7933931/97337以瞭解如何消除警告。如果這些可以返回對象,那麼你需要確保它們不會有額外的保留,這只是一個兔子洞,你可能不應該下去(或者至少應該問一個新的問題)。

+0

「你用這個來調用任意選擇器的事實表明它們中的一些具有結構或浮點返回」 - 返回類型總是'void',這意味着'objc_msgSend'是正確的API使用? – aroth

+0

如果是這樣,你可能不會只在一個平臺上發生崩潰。他們都採取一個參數沒有可變參數嗎?我會嘗試將所有可能的選擇器放在靜態代碼中,並編譯它並查看組件(助手中的「彙編器視圖」)。確保它們都編譯成完全相同的設置和函數調用。正如我所說,objc_msgSend是棘手和平臺特定的。很難做到這一點。 –