I've got a weird situation where cJSON_Delete() is causing my application to crash. Does anybody see a problem with the below code? The cjSON_Print() call works fine, the printed JSON looks fine, but cJSON_Delete() crashes.
cJSON *cjMsg=NULL, *cjStart=NULL, *cjEnd=NULL, *cjDateTime=NULL, *cjDateTime2=NULL, *cjTimeZone=NULL;
char *string=NULL, TZ[256]="UTC", dateStr[256]="";
cjMsg = cJSON_CreateObject();
cjTimeZone = cJSON_CreateString(TZ);
cjStart = cJSON_CreateObject();
strcpy(dateStr, "2025-06-01T14:00:00");
cjDateTime = cJSON_CreateString(dateStr);
cJSON_AddItemToObject(cjMsg, "start", cjStart);
cJSON_AddItemToObject(cjStart, "dateTime", cjDateTime);
cJSON_AddItemToObject(cjStart, "timeZone", cjTimeZone);
strcpy(dateStr, "2025-06-01T15:00:00");
cjEnd = cJSON_CreateObject();
cjDateTime2 = cJSON_CreateString(dateStr);
cJSON_AddItemToObject(cjMsg, "end", cjEnd);
cJSON_AddItemToObject(cjEnd, "dateTime", cjDateTime2);
cJSON_AddItemToObject(cjEnd, "timeZone", cjTimeZone);
string = cJSON_Print(cjMsg);
printf("%s\n", string);
cJSON_Delete(cjMsg);
free(string);
Specifically where I add cjTimeZone to two different objects? The crash will go away if I create a second variable called *cjTimeZone2, assign it to the same TZ string, and add that to cjEnd instead of cjTimeZone.
Also help me understand in general the idea of re-using cJSON variables. In the above example, I had originally used cjDateTime twice, just assigning it to a different string, then adding it to both cjStart and cjEnd. This caused no problems. (I started using cjDateTime2 in an attempt to fix my problem, but it turned out to be just cjTimeZone).
I do this kind of thing all over my application, and it's never caused a problem, until this specific example. If someone could point out the error of my ways I'd appreciate it.
cjTimeZone = cJSON_CreateString(TZ);
// ...
cJSON_AddItemToObject(cjStart, "timeZone", cjTimeZone);
// ...
cJSON_AddItemToObject(cjEnd, "timeZone", cjTimeZone);
cJSON_AddItemToObject()
makes the object the item is being added to assume ownership of it - when the object is deleted, it frees up that item's memory. You're adding both cjStart
and cjEnd
to cjMsg
, and thus when you call cJSON_Delete()
on cjMsg
, the cjTimeZone
value is freed twice - which can certainly manifest itself in your program crashing.
The easiest way to resolve this is probably to use cJSON_AddItemReferenceToObject()
instead, which doesn't transfer ownership, and then explicitly call cJSON_Delete(cjTimeZone)
after deleting cjMsg
.