繁体   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