Do i need to free memory for C strings obtained from xpc_dictionary_get_string?

I am using C APIs for XPC communication.

When my XPC server gets a xpc_dictionary as a message, I use xpc_dictionary_get_string to get the string which is of type const char*. Afterwards, when I try to free up the memory for the string, I get an error.

I could not find any details on why this happens.

Does XPC handle the lifecycle of these C strings ?


I did some tests to see the behaviour.

The following code snippet prints a string temp before and after releasing the dictionary memory.

char* string = "dummy-string"; 
xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_string(dict, "str", string); 
const char* temp = xpc_dictionary_get_string(reply, "str"); 
  
printf("temp before release: %s\n", temp); 
xpc_release(reply); 
printf("temp after release: %s\n", temp);

output:

# temp before release: dummy-string
# temp after release: 

I tried to free the variable temp before and after releasing dict .

char* string = "dummy-string";
xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_string(dict, "str", string); 
const char* temp = xpc_dictionary_get_string(dict, "str"); 
printf("temp before release: %s\n", temp);   

free((void *)temp); // case 1
xpc_release(dict); 
// free((void *)temp); // case 2
printf("temp after release: %s\n", temp);

in both the cases i got the output:

# temp before release: dummy-string
# app(18502,0x1f02fc840) malloc: Double free of object 0x145004a20
# app(18502,0x1f02fc840) malloc: *** set a breakpoint in malloc_error_break to debug
# SIGABRT: abort
# PC=0x186953720 m=0 sigcode=0
# signal arrived during cgo execution
# ...
# ...
Answered by DTS Engineer in 826330022

XPC follows the CF rules, that is:

  • Routines with create or copy in the name return values that you must explicitly free [1].

  • Routines without that, and especially those with get in the name, return values that you don’t need to free.

Implicit in the second point is that the value is dependent on the original type.

This is documented pretty well in the xpc_object man page.

If you’re working with the XPC C API then I strongly recommend that you pay close attention to the man pages and the doc comments in the headers. It’d be nice if all of this were integrated into the core documentation, but that’s not the case )-:

I talk about that more in Availability of Low-Level APIs.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Unless the value is an object and you’re using ARC, in which case it manages the references for you.

I guess that the char* that you get from xpc_dictionary_get_string points inside the dictionary, and not to a copy. I.e. the bytes are freed when the dictionary is destroyed.

Accepted Answer

XPC follows the CF rules, that is:

  • Routines with create or copy in the name return values that you must explicitly free [1].

  • Routines without that, and especially those with get in the name, return values that you don’t need to free.

Implicit in the second point is that the value is dependent on the original type.

This is documented pretty well in the xpc_object man page.

If you’re working with the XPC C API then I strongly recommend that you pay close attention to the man pages and the doc comments in the headers. It’d be nice if all of this were integrated into the core documentation, but that’s not the case )-:

I talk about that more in Availability of Low-Level APIs.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Unless the value is an object and you’re using ARC, in which case it manages the references for you.

Do i need to free memory for C strings obtained from xpc_dictionary_get_string?
 
 
Q