2010-04-29 62 views
0

它不關心這個:Xcode的「構建和分析」的作用範圍是什麼?

NSString* leaker() 
{ 
return [[NSString alloc] init]; 
} 

我認爲這將是足夠聰明,檢查是否有任何的代碼路徑可以調用該函數不釋放其返回值(通常我不會這樣的代碼,我只是測試分析儀)。

據報道這是一個泄漏:

NSString* leaker() 
{ 
NSString* s = [[NSString alloc] init]; 
[s retain]; 
return s; 
} 

,但不是這個:

NSString* leaker() 
{ 
NSString* s = [[NSString alloc] init]; 
// [s retain]; 
return s; 
} 

這似乎特別弱到我。它只在本地範圍內進行分析嗎?如果這個工具無法接受這樣的事情,我怎麼能期望它能夠彌補我可能犯的實際錯誤?

回答

4

clang不執行任何程序間分析,至少不是。即使這樣做了,它也未必會抓住這個「錯誤」 - 潛在的代碼路徑的排列往往會呈指數級增長,使其變得實際上不可能。

clang適用於「大部分時間」工作的一套啓發式方法。值得慶幸的是,可可內存管理規則往往相當統一,所以啓發式對大多數用途都有效。您提供的具體示例並未真正涵蓋內存管理規則,但我認爲大多數人(包括我自己)都傾向於將您的示例歸類爲「您通過API記錄了leaker()的調用者是負責返回的對象「。這基本上類似於- (NSString *)init...風格的方法。

clang知道以init...開頭的方法會返回一個'未發佈'的對象,並且調用者有責任確保它被正確釋放。這構成了啓發式技術的核心部分 - 它不需要整個程序或者程序間分析來進行大量的引用計數檢查 - 如果本地代碼塊通過init...方法獲得對象,則本地代碼塊需要確保它正確released。自然,如果本地代碼塊和有問題的對象是init...方法本身的一部分,它將被相同的「規則」覆蓋,所以它會得到一個異常。

你可能想要的是一樣的東西:

NSString* leaker() __attribute__((ns_returns_retained)) 
{ 
return [[NSString alloc] init]; 
} 

這讓分析器知道leaker()返回「保留」的對象,調用者負責妥善釋放它。雖然我沒有測試此,我強烈懷疑「泄漏」將在這裏leaker()稱爲點進行檢測,即:

void test(void) 
{ 
    NSString *leaked = leaker(); 
    // Previous line should be caught as a "leak" by clang. 
} 

這是任何靜態分析的侷限性不幸的一個,不只是clang

相關問題