簡體   English   中英

CFSTR()是否分配內存?

[英]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.

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