I understood the CFSTR() documentation to indicate that it allocates memory. 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. It's wrapping the static string, but surely it has to allocate a CFString class struct to do so. 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. The leaks reported by valgrind don't vary with the loop size. 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. Others say it's like Objective C's @"String"
literal syntax. The CFString reference mentions needing -fconstant-cfstrings
on gcc 3.3. 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.
So this seems likely the answer is, " It doesn't allocate on MacOS X or iOS ".
I don't know how to verify they're actually in the executable as CFStringRefs, but otool -tV
says:
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.
As you discovered, on Apple platforms, CFSTR
uses a compiler built-in to generate the string at compile time. It is embedded in the executable as a fully-constructed, usable object; the program doesn't perform any allocation at runtime for 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. Instead, at runtime, it calls the private library function __CFStringMakeConstantString
. You can find the source code of this function in CFString.c
. It keeps a hash table that maps the argument (as a C string) to a 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. The memory is accessible by any call to CFSTR
with the same string argument, so calling it a “leak” is questionable.
CFSTR
is a function-like macro that takes a const char *
and returns a 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.
(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.)
EDIT : As far as de-duplication goes, I wouldn't be surprised if it searches a heap of existing initialized CFStringRef
s. Again, this should be an implementation detail and shouldn't affect the patterns you use.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.