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