[英]Does CFSTR() allocate memory?
我理解CFSTR()文檔表明它分配了內存。 它可以在失敗時返回NULL,並且結果可用,直到程序終止,無論是否調用CFRelease()或刪除引用。 它包裝了靜態字符串,但肯定必須分配一個CFString類結構來實現。 因此,在長期運行的程序中使用它是不合適的。
但是,經過一番回擊,我嘗試了以下測試程序。 我沒有看到內存占用量增加top
。 valgrind報告的泄漏不隨循環大小而變化。 是否有重復數據刪除?
#include <CoreFoundation/CFString.h>
#include <stdio.h>
int main(void) {
int count = 0;
int chars = 0;
for (int i = 0; i < 100000000; i++) {
CFStringRef str = CFSTR("Goodbye.");
if (str) {
count++;
chars += CFStringGetLength(str);
// Drop reference!
}
}
printf("%d strings, %d chars\n", count, chars);
CFStringRef str = CFSTR("Hello, World.");
CFShowStr(str);
}
另一位提問者報告稱 ,CFSTR() 確實在Windows 上泄露。 其他人說它就像Objective C的@"String"
字面語法。 CFString參考提到在gcc 3.3上需要-fconstant-cfstrings
。 那么宏是否使用魔術編譯器擴展來在構建時創建它們?
在我的MacOS X 10.8.5機器上,CoreFoundation / CFString.h將CFSTR定義為__builtin___CFStringMakeConstantString
除了在Windows或Linux上,它使用非內置版本。
因此,似乎答案是“ 它不會在MacOS X或iOS上分配 ”。
我不知道如何驗證它們實際上是作為CFStringRefs在可執行文件中,但是otool -tV
說:
leaq 0x1c8(%rip), %rax ## Objc cfstring ref: @"Goodbye."
指令指針相對尋址是一些確認,而leaq
意味着它不會調用任何可以分配的東西。
正如您所發現的,在Apple平台上, CFSTR
使用內置的編譯器在編譯時生成字符串。 它作為一個完全構造的可用對象嵌入在可執行文件中; 程序不會在運行時為CFSTR
執行任何分配。 編譯器在單個轉換單元中合並重復的字符串對象。 我不確定鏈接器是否跨目標文件合並重復項。
在其他平台上,Apple不控制編譯器,因此它不能使用內置的編譯器將構造對象嵌入可執行文件中。 相反,在運行時,它調用私有庫函數__CFStringMakeConstantString
。 您可以在CFString.c
找到此函數的源代碼。 它保留了一個哈希表,將參數(作為C字符串)映射到CFString
。 這是“重復數據刪除”。 它通常不會從表中刪除條目。 因此,傳遞給CFSTR
每個唯一C字符串將分配一些持續存在直到程序存在的內存。 任何使用相同字符串參數的CFSTR
調用都可以訪問內存,因此將其稱為“泄漏”是值得懷疑的。
CFSTR
是一個類似函數的宏,它接受一個const char *
並返回一個CFStringRef
。
CFStringRef CFSTR (
const char *cStr
);
如您所述,文檔提供了一些有趣的警告。 我個人會將它們視為實現細節,並管理您從中獲取的CFStringRef
,因為它由創建規則保留,相應地平衡了retain / release調用。
(至於它可能分配或不分配的原因,我認為編譯器可以選擇通過創建一個不朽的CFStringRef
來優化CFSTR()
調用,就像擁有NSString *str = @"MyString!";
會這樣做,但我沒有數據支持這個。)
編輯 :就重復數據刪除而言,如果它搜索一堆現有的初始化CFStringRef
,我不會感到驚訝。 同樣,這應該是一個實現細節,不應該影響您使用的模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.