Does Swift provide a way to store a C-string ( UnsafePointer<CChar> ) with a static lifetime? Something like a hypothetical:
let s: UnsafePointer<CChar> = "abc"
Where s has a stable pointer, pointing to a constant in the data section of the app's binary, just like a C string constant.
Context
I want to use kSMRightBlessPrivilegedHelper, which is declared as a C macro:
/*!
* @abstract
* The authorization rights key for blessing and installing a privileged helper
* tool.
*/
#define kSMRightBlessPrivilegedHelper \
"com.apple.ServiceManagement.blesshelper"
Since it's just a string literal in C, it has a constant address and you don't have to worry about alloc/freeing it.
But in Swift, it imports as Swift.String , and you have to worry about the lifetime of the scoped pointer you get with
kSMRightBlessPrivilegedHelper.withCString { thisDoesntOutliveTheClosure in
// ...
}
I'd like to have the pointer outlive that closure scope. I'm okay with "leaking it", by having the pointer be allocated for the whole lifetime of the program (it's tiny)
private var _helperString: UnsafeMutableRawPointer!
var helperString: UnsafeMutableRawPointer {
if _helperString == nil {
kSMRightBlessPrivilegedHelper.withCString { s in
let len = strlen(s)
_helperString = malloc(len + 1)!
memmove(_helperString, s, len + 1)
}
}
return _helperString!
}
If StaticString is not an option, you have to expose this pointer through another C function.
One comment: By being a macro, this line itself rely on linker to dedup all static string at link time. You probably want to modify the C side of things a bit anyway.
If I'm not mistaken, the pointer you get back from doing that is only guaranteed to be valid for the lifetime of the call of some_C_function. If some_C_function stashes it away somewhere, it'll be dangling.
very true, but i think such C api would be rather an exception than a rule and would be documented to have this behaviour, otherwise any code that does anything like this would break:
void foo() {
char s[...];
populate s
some_C_function(s);
}
void bar() {
char* s = malloc(...);
populate s
some_C_function(s);
free(s);
}
i think such C api would be rather an exception than a rule
It does crop up pretty regularly, often when there’s some complicated set of structures that are set up and passed into a function call. One that I hit commonly is AuthorizationCopyRights.