简体   繁体   English

CFSTR()是否分配内存?

[英]Does CFSTR() allocate memory?

I understood the CFSTR() documentation to indicate that it allocates memory. 我理解CFSTR()文档表明它分配了内存。 It can return NULL on failure, and the result is available until the program terminates regardless of whether one calls CFRelease() or drops the reference. 它可以在失败时返回NULL,并且结果可用,直到程序终止,无论是否调用CFRelease()或删除引用。 It's wrapping the static string, but surely it has to allocate a CFString class struct to do so. 它包装了静态字符串,但肯定必须分配一个CFString类结构来实现。 And as such it's not appropriate to use in long-running programs. 因此,在长期运行的程序中使用它是不合适的。

However, after some pushback on this, I tried the following test program. 但是,经过一番回击,我尝试了以下测试程序。 I don't see the memory footprint in top increase. 我没有看到内存占用量增加top The leaks reported by valgrind don't vary with the loop size. valgrind报告的泄漏不随循环大小而变化。 Is there de-duplication happening? 是否有重复数据删除?

#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);
}

Another asker reported that CFSTR() does leak on Windows. 另一位提问者报告称 ,CFSTR() 确实在Windows 泄露。 Others say it's like Objective C's @"String" literal syntax. 其他人说它就像Objective C的@"String"字面语法。 The CFString reference mentions needing -fconstant-cfstrings on gcc 3.3. CFString参考提到在gcc 3.3上需要-fconstant-cfstrings So does the macro use a magic compiler extension to create these at build time? 那么宏是否使用魔术编译器扩展来在构建时创建它们?

On my MacOS X 10.8.5 machine, CoreFoundation/CFString.h defines CFSTR as __builtin___CFStringMakeConstantString except on Windows or Linux, where it uses a non-builtin version. 在我的MacOS X 10.8.5机器上,CoreFoundation / CFString.h将CFSTR定义为__builtin___CFStringMakeConstantString 除了在Windows或Linux上,它使用非内置版本。

So this seems likely the answer is, " It doesn't allocate on MacOS X or iOS ". 因此,似乎答案是“ 它不会在MacOS X或iOS上分配 ”。

I don't know how to verify they're actually in the executable as CFStringRefs, but otool -tV says: 我不知道如何验证它们实际上是作为CFStringRefs在可执行文件中,但是otool -tV说:

leaq    0x1c8(%rip), %rax ## Objc cfstring ref: @"Goodbye."

Instruction pointer relative addressing is some confirmation, and leaq means it's not calling anything which could allocate. 指令指针相对寻址是一些确认,而leaq意味着它不会调用任何可以分配的东西。

As you discovered, on Apple platforms, CFSTR uses a compiler built-in to generate the string at compile time. 正如您所发现的,在Apple平台上, CFSTR使用内置的编译器在编译时生成字符串。 It is embedded in the executable as a fully-constructed, usable object; 它作为一个完全构造的可用对象嵌入在可执行文件中; the program doesn't perform any allocation at runtime for CFSTR . 程序不会在运行时为CFSTR执行任何分配。 The compiler merges duplicate string objects within a single translation unit. 编译器在单个转换单元中合并重复的字符串对象。 I'm not sure if the linker merges duplicates across object files. 我不确定链接器是否跨目标文件合并重复项。

On other platforms, Apple doesn't control the compiler, so it can't use a compiler built-in to embed a constructed object in the executable. 在其他平台上,Apple不控制编译器,因此它不能使用内置的编译器将构造对象嵌入可执行文件中。 Instead, at runtime, it calls the private library function __CFStringMakeConstantString . 相反,在运行时,它调用私有库函数__CFStringMakeConstantString You can find the source code of this function in CFString.c . 您可以在CFString.c找到此函数的源代码。 It keeps a hash table that maps the argument (as a C string) to a CFString . 它保留了一个哈希表,将参数(作为C字符串)映射到CFString This is the “de-duplication”. 这是“重复数据删除”。 It generally doesn't remove entries from the table. 它通常不会从表中删除条目。 So each unique C string passed to CFSTR will allocate some memory that persists until the program exists. 因此,传递给CFSTR每个唯一C字符串将分配一些持续存在直到程序存在的内存。 The memory is accessible by any call to CFSTR with the same string argument, so calling it a “leak” is questionable. 任何使用相同字符串参数的CFSTR调用都可以访问内存,因此将其称为“泄漏”是值得怀疑的。

CFSTR is a function-like macro that takes a const char * and returns a CFStringRef . CFSTR是一个类似函数的宏,它接受一个const char *并返回一个CFStringRef

CFStringRef CFSTR (
    const char *cStr
);

As you mention, the documentation provides a few interesting caveats. 如您所述,文档提供了一些有趣的警告。 I would personally treat them as implementation details and manage the CFStringRef you get from it as being retained by the create rule, balancing retain/release calls accordingly. 我个人会将它们视为实现细节,并管理您从中获取的CFStringRef ,因为它由创建规则保留,相应地平衡了retain / release调用。

(As far as the reason why it may or may not allocate, I think the compiler has the option to optimize out a CFSTR() call by creating an immortal CFStringRef just like having NSString *str = @"MyString!"; would do, but I have no data to support this.) (至于它可能分配或不分配的原因,我认为编译器可以选择通过创建一个不朽的CFStringRef来优化CFSTR()调用,就像拥有NSString *str = @"MyString!";会这样做,但我没有数据支持这个。)

EDIT : As far as de-duplication goes, I wouldn't be surprised if it searches a heap of existing initialized CFStringRef s. 编辑 :就重复数据删除而言,如果它搜索一堆现有的初始化CFStringRef ,我不会感到惊讶。 Again, this should be an implementation detail and shouldn't affect the patterns you use. 同样,这应该是一个实现细节,不应该影响您使用的模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM