2014-02-27 51 views
2

我有我要調試的方法:訪問類的斷點條件

-(void)doAThingWithObject:(BaseDataObject *)dataObject //called VERY often 

而且我有這個方法,我只希望在BaseDataObject的某些子類打破內部的Xcode的斷點,所以我添加一個斷點W /有條件以檢查類:

[dataObject isKindOfClass:[SubClassOfBaseDataObject class]]

然而,這樣做的一個分析錯誤的結果!

Stopped due to an error evaluating condition of breakpoint 11.1: "[dataObject isKindOfClass:[SubClassOfBaseDataObject class]]" 
Couldn't parse conditional expression: 
error: no known method '+class'; cast the message send to the method's return type 
error: 1 errors parsing expression 

我已經確保導入文件中的所有類,但調試器不知道我在條件中引用了哪些類。

但是,創建的臨時變量中的斷點前該方法在所述類別:

Class subClassCheck = [SubClassOfBaseDataObject class]; 

以及更新所述斷點條件,以引用臨時變量:

[dataObject isKindOfClass:subClassCheck] 

拋出沒有錯誤。

當談到斷點條件時,我有點新手,有人可以解釋爲什麼我的第一種方法不起作用嗎?

回答

8

一個基於Cocoa這樣的大型框架的調試代碼的複雜情況是,編譯器不能發出或調試器在你包含的框架的整個閉包中消耗每個類型和函數。所以編譯器使用一些啓發式方法來減少生成的調試信息的數量。它只會爲實際使用的類型發佈類型信息,而函數/ ObjC方法信息是定義該方法的地方(而不是在頭文件中聲明的)。還有一點小問題,lldb會讀取方法的類型信息ObjC運行時,儘管這些信息並不完整,因爲它是針對運行時而不是針對調試器的......因此,我們有時似乎知道有關違反先前規則的ObjC方法的事情。

另一個需要注意的重要事項是,返回比指針大的東西(比如NSMakeRect等)的函數的調用約定是這樣的,即如果調試器調用函數時認爲它返回一個指針,並且它實際上返回一個更大的結構,該行爲將導致程序中的堆棧損壞。如果你幸運的話,你會在你繼續時立即崩潰,但如果你不幸,它會改變一些數據的價值,並導致你花費數小時來追逐一些實際上由調試器引起的有趣行爲。因此調試器將拒絕調用其無法確定的返回類型的函數。

無論如何,你得到的錯誤是因爲調試器找不到你的對象上「+ class」方法的調試信息。這並不令人感到意外,因爲「class」是NSObject的一種方法,而不是您的類。我不確定爲什麼我們無法在運行時找到它,也許是因爲它是一個類方法?這值得一個錯誤。我們顯然確實從運行時獲得了isKindOfClass的類型:或者您的解決方法也會失敗。

在這種情況下,由於您確實知道類方法的返回類型,因此您可以通過將其顯式轉換爲斷點表達式來解決調試器缺乏知識的問題。在調試器的表達式解析器中投射函數返回有兩個目的,一個是常規的C語言函數,另一個是告訴調試器函數的返回類型,否則它將無法解決。一種僅用於返回類型的簡短原型。

因此,像:

[dataObject isKindOfClass: (Class) [SubClassOfBaseDataObject class]] 

應該工作而無需改變你的代碼。

另請注意,斷點條件使用與「expr」或「print」命令相同的機制運行。所以實驗斷點命令最簡單的方法是設置一個無條件斷點,點擊它,然後進入lldb控制檯,並用「打印」來玩,直到找到可用的東西。

+0

這是迄今爲止我在StackOverflow上收到的最令人滿意的答案。它描述了我發現的內容,解釋了我找到的環境,甚至在與調試器打交道的過程中,我會用其他方式警告我。 我也很高興我的期望是(某種程度上)正確的,這是一個值得發現的錯誤報告。在此期間,我可以採取一種解決方法?人們還能要求什麼? – Andrew