簡體   English   中英

ARC和__unsafe_unretained

[英]ARC and __unsafe_unretained

我想我有ARC的一個很好的了解和正確使用的情況下選擇合適的一生預選賽( __strong__weak__unsafe_unretained__autoreleasing )。 但是,在測試中,我發現了一個對我沒有意義的示例。

據我了解, __weak__unsafe_unretained都不會添加保留計數。 因此,如果沒有其他指向該對象的__strong指針,則會立即將其釋放(不可變字符串是該規則的一個例外)。 此過程的唯一區別是__weak指針被設置為nil,而__unsafe_unretained指針被單獨保留。

如果我創建一個指向簡單自定義對象(由一個NSString屬性組成)的__weak指針,則嘗試訪問屬性時會看到預期的(空)值:

Test * __weak myTest = [[Test alloc] init];
myTest.myVal = @"Hi!";
NSLog(@"Value: %@", myTest.myVal); // Prints Value: (null)

同樣,由於生成的懸空指針,我希望__unsafe_unretained生存期限定符會導致崩潰。 但是,事實並非如此。 在下一個測試中,我看到了實際值:

Test * __unsafe_unretained myTest = [[Test alloc] init];
myTest.myVal = @"Hi!";
NSLog(@"Value: %@", myTest.myVal); // Prints Value: Hi!

為什么不取消分配__unsafe_unretained對象?

[編輯] :正在釋放對象...如果我嘗試用NSLog(@"%@", myTest);替換第2-3行NSLog(@"%@", myTest); 應用程序崩潰(第一行之后立即調用Test重寫的dealloc )。 我知道即使使用__unsafe_unretained ,不可變的字符串仍將繼續可用,並且指向NSString的直接指針將起作用。 我只是對我可以在已釋放對象上設置屬性(第2行)感到驚訝,並且以后可以從指向它所屬的已釋放對象的指針中取消引用該屬性(第3行)! 如果有人可以解釋,那肯定會回答我的問題。

因為objc中的常量字符串是指向堆地址的常量指針,並且該地址仍然有效。

評論后編輯:

也許是因為測試對象地址處的內存尚未被覆蓋並且仍包含該對象? 投機....

我只是對我可以在已釋放對象上設置屬性(第2行)感到驚訝,並且以后可以從指向它所屬的已釋放對象的指針中取消引用該屬性(第3行)! 如果有人可以解釋,那肯定會回答我的問題。

釋放對象時,它不會歸零。 由於您有一個指向已釋放對象的指針,並且屬性值存儲在該指針的某個偏移處,因此有可能在釋放之后成功存儲和檢索該屬性值,也很有可能由於某種原因而使所有內容崩潰或其他。

您的代碼工作非常脆弱,請嘗試使用“調試時顯示反匯編”進行調試並逐步執行,您可能會遇到訪問沖突,或者刪除Xcode本身。

對於C,Objective-C,C ++或其他任何家族中發生的奇怪事情,您永遠不會感到驚訝。 相反,請為如此少見的奇怪事情保留您的驚喜!

通過實現它的-dealloc方法並添加一些簡單的日志記錄,您可以看到何時釋放Test

但是,即使Test被立即釋放,它在調用myVal時在RAM中占用的內存也可能保持不變。

@"hi!" 產生一個靜態的全局常量字符串實例,該實例實際上是一個單例。 因此,它永遠不會被釋放,因為它並不是一開始就真正分配的(至少,它實際上不是正常的堆分配)。

每當您要探索對象的壽命問題時,請始終使用NSObject的子類來保證行為並通過覆蓋行為使其易於掛入日志掛鈎。

那里沒什么奇怪的……您需要至少有1個對對象的強烈引用才能使其存活。

Test * anTest = [[Test alloc] init];
Test * __weak myTest = anTest;
myTest.myVal = @"Hi!";
NSLog(@"Value: %@", myTest.myVal); // Prints Value: (Hi)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM