2017-05-27 71 views
2

最近我注意到了Xcode中Objective C內存管理的奇怪行爲。 下面是代碼:Xcode 8.3中奇怪的Clang行爲

#import <Foundation/Foundation.h> 

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     NSString *firstString = [[NSString alloc] initWithString: @"Hello"]; 
     NSString *secondString = firstString; 
     [firstString release]; 
     NSLog(@"%@", secondString); 
    } 
    return 0; 
} 

我認爲,secondString釋放firstString的NSLog應該產生錯誤後。 但是,此代碼不會產生任何錯誤併成功地打印「Hello」字符串。 我手動編譯和這樣的命令運行代碼並沒有發現任何錯誤太:

% clang -framework Foundation -fno-objc-arc main.m && ./a.out 

我試圖編譯這段代碼在線的Objective-C編譯器(GCC)(http://rextester.com/l/objectivec_online_compiler)和錯誤是發生了。 我在做什麼錯? 在Xcode中關閉ARC支持。 在此先感謝。

回答

2

如果(Xcode的「產品」菜單上轉變 + 命令 + 在Xcode或「分析」)進行靜態分析,它會提醒你,你想引用一個對象它被釋放之後:

static analysis

的問題是,在手動引用計數的代碼,以釋放對象的引用設置爲nil自動。因此,除非您手動輸入nil這些指針,否則您最終可能會懸掛指向先前已解除分配的對象的指針。

靜態分析儀非常適合識別這些類型的問題。我建議在繼續之前確保您有靜態分析儀的清潔健康計劃。

在這種情況下的第二道防線是啓用殭屍運行時調試選項。這將報告在釋放對象後與對象交互的任何嘗試。當您編輯Xcode目標的方案時,可以在「診斷」部分中啓用殭屍。

不幸的是,你使用的是NSString,它不遵循典型的內存管理規則(它可以保留自己對字符串的引用,所以當你以其他方式期待它們時,它們並不總是被釋放)。

考慮與你類似的例子,除了與自定義類:

#import <Foundation/Foundation.h> 

@interface MyObject: NSObject 
@end 
@implementation MyObject 
@end 

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     MyObject *firstObject = [[MyObject alloc] init]; 
     MyObject *secondObject = firstObject; 
     [firstObject release]; 
     NSLog(@"%@", secondObject); 
    } 
    return 0; 
} 

如果你與殭屍運行它,你會得到相應的錯誤信息,表明你想用互動釋放的實例:

2017年5月27日08:19:18.154033-0700 MyApp的[36888:7215135] *** - [MyObject來isProxy]:消息發送到釋放的實例0x100303620

但是,您可能不會從NSString收到此警告。底線,應避免從NSString行爲中得出更廣泛的內存管理結論。相反,依靠Xcode的靜態分析器和殭屍。 (請注意,在完成調試應用程序時,請記得關閉殭屍程序。)

+0

感謝您的詳細解答!我嘗試並得到與其他對象(不是NSString)的預期行爲。 – akozin

+0

'NSString'因這種行爲而臭名昭着。我不熟悉那些表現得如此異常的人,但這是可能的。如果不知道其他課程是否遇到類似問題,我不能進一步評論。但如果你按照靜態分析儀的建議,你會沒事的。 – Rob