0

正如我們所知,在X代碼中編程objective-c用於表示處理對象的手動引用計數。之後,引入了垃圾收集功能,現在已被自動引用計數(ARC)取代。垃圾收集應用程序加載ARC二進制

在過去,我有一個用GC開發的應用程序,可以使用函數調用dlopen加載庫。這要求加載庫與主機應用程序的庫匹配,並使用GC。如果庫是用ARC構建的,dlopen會失敗。當然,這種不相容性是可以預料的。

系統首選項應用程序就是一個很好的例子。它使用垃圾收集: -

otool -oV /Applications/System\ Preferences.app/Contents/MacOS/System\ Preferences | tail -3 
Contents of (__DATA,__objc_imageinfo) section 
version 0 
flags 0x2 OBJC_IMAGE_SUPPORTS_GC 

直到10.7 so did the preference panes which it loads。但是,在10.8的系統預置應用程序仍然使用GC,但其中一些IT負載窗格別: -

otool -oV /System/Library/PreferencePanes/Network.prefPane/Contents/MacOS/Network | tail -3 
Contents of (__DATA,__objc_imageinfo) section 
    version 0 
    flags 0x0 

那麼,這是怎麼回事呢? System Preferences應用程序的垃圾收集機制如何處理ARC編譯的窗格?他們是否泄露了內存,或者是否存在某種轉換?

回答

2

ARC不會更改您熟悉的規則,但仍必須爲整個過程啓用或禁用垃圾回收。

要了解系統偏好設置的工作方式,請仔細查看__objc_imageinfo的標誌。下面是Clang definitions那些標誌:

enum ImageInfoFlags { 
    eImageInfo_FixAndContinue  = (1 << 0), // This flag is no longer set by clang. 
    eImageInfo_GarbageCollected = (1 << 1), 
    eImageInfo_GCOnly    = (1 << 2), 
    eImageInfo_OptimizedByDyld  = (1 << 3), // This flag is set by the dyld shared cache. 

    // A flag indicating that the module has no instances of a @synthesize of a 
    // superclass variable. <rdar://problem/6803242> 
    eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang. 
    eImageInfo_ImageIsSimulated = (1 << 5) 
}; 

的10.8+版本系統偏好有垃圾回收標誌設置,但不是唯一GC-標誌。這意味着它是用-fobjc-gc構建的,並且包含支持垃圾收集和保留/釋放的代碼。因此,可以通過啓用或禁用通過OBJC_DISABLE_GC環境變量的GC來運行GC。綜觀的Info.plist該系統偏好正是它:

<key>LSEnvironment</key> 
<dict> 
    <key>OBJC_DISABLE_GC</key> 
    <string>YES</string> 
</dict> 

有了這種結合系統偏好設置啓動禁用垃圾收集,並且可以加載預置面板沒有GC支持和那些既GC建成並保留/ release支持通過-fobjc-gc。如果用戶嘗試打開需要垃圾回收的首選項窗格(使用-fobjc-gc-only構建),系統首選項會通知用戶需要重新啓動才能加載該窗格。如果授予權限,則應用程序會使用OBJC_DISABLE_GC = NO重新啓動。此時它可以加載需要GC支持的偏好窗格以及使用GC和保留/發佈支持構建的偏好窗格。如果用戶隨後嘗試加載沒有GC支持的偏好窗格,則應用程序需要重新啓動。

因此,這裏沒有GC和非GC魔術,只需通過系統首選項UI實現向後兼容機制,而不需要同時加載所有首選項窗格。

+0

正是我在找的東西。感謝您的解釋。 – TheDarkKnight

0

ARC 實際上向後下非ARC編譯,所以混合ARC代碼與非ARC代碼庫和框架兼容不是不尋常的。它的工作方式是通過使用標誌在編譯時切換ARC /關閉:

-fno-objc-arc 
-fobjc-arc 

例如,您可以設定目標來構建默認爲ARC,併爲代碼不是圓弧你在特定的構建階段將能夠切換到非ARC編譯器。

很明顯,它比我剛纔提到的要多得多,但至少你知道非ARC與ARC混合是非常可能的。

+0

弧向後兼容手動引用計數,但不是GC,據我所知。 「使用Apple的垃圾收集器,整個應用程序都運行在GC之下,或者它們都不會運行」 - https://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html – TheDarkKnight

+0

@ Merlin069,你還會如何解釋otool輸出?如果GC不能與ARC共存,那麼蘋果公司文檔中就沒有提到這一點(我見過);他們確實指出GC [1](https://developer.apple.com/library/mac/documentation/cocoa/reference/NSGarbageCollector_class/Introduction/Introduction.html)已棄用,而ARC [²](https:/ /developer.apple.com/library/Mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html)應該繼續前進;我不確定爲什麼有人會想要同時使用這兩個。 –

+0

也許你誤會了我。我知道它的工作原理,可以從系統偏好和otool輸出中看到。但是,如果應用程序正在使用垃圾回收進行內存管理,那麼當它遇到動態庫的代碼不是GC'd時它會執行什麼操作?我不問如何啓用該功能,但從學術角度來看,運行時發生了什麼? – TheDarkKnight