[英]Segmentation Fault when Modifying a cJSON Struct Created by Parsing a String Literal
當使用cJSON解析字符串文字時,在釋放cJSON結構時遇到分段錯誤。
原始代碼如下:
char* jsonStr = "{ \"command\" : { \"param1\": \"value1\", \"param2\": \"value2\" } }";
cJSON *jsonMsg = cJSON_Parse(jsonStr);
cJSON *command = CJSON_GetObjectItem(jsonMsg, "command");
cJSON_GetObjectItem(command,"param1")->valuestring = "new value 1";
cJSON_Delete(jsonMsg); // <— segmentation fault
當我第一次遇到這個問題時,我對這種行為感到困惑。 該示例與cJSON 文檔中的示例非常相似。
我第一次嘗試解決方案是設置“ param1”的類型 ,以便cJSON_Delete()函數不會嘗試釋放內存。 也就是說,在cJSON-> type成員中設置“ cJSON_IsReference”標志。
更新的代碼是:
char* jsonStr = "{ \"command\" : { \"param1\": \"value1\", \"param2\": \"value2\" } }";
cJSON *jsonMsg = cJSON_Parse(jsonStr);
cJSON *command = CJSON_GetObjectItem(jsonMsg, "command");
cJSON_GetObjectItem(command,"param1")->valuestring = "new value 1";
cJSON_GetObjectItem(command,"param1")->type |= cJSON_IsReference;
cJSON_Delete(jsonMsg);
最終的解決方案是將原始消息的內容傳輸到新的cJSON對象中。 這樣可以防止由於cJSON_Parse()分配的孤立內存而導致的內存泄漏。
最終代碼如下所示:
char* jsonStr = "{ \"command\" : { \"param1\": \"value1\", \"param2\": \"value2\" } }";
cJSON *jsonMsg = cJSON_Parse(jsonStr);
cJSON *command = CJSON_GetObjectItem(jsonMsg, "command");
cJSON *jsonRes, *command;
jsonRes = cJSON_CreateObject();
command = cJSON_CreateObject()
cJSON_AddItemToObject(jsonRes, "command", command);
cJSON_AddStringToObject(command, cJSON_GetObjectItem(command,"param1")->string, "new value 1");
cJSON_AddItemToObject(jsonRes, "command", command = cJSON_CreateObject());
cJSON_AddStringToObject(command,
cJSON_GetObjectItem(command,"param2")->string,
cJSON_GetObjectItem(command,"param2")->valuestring);
cJSON_Print(jsonRes);
cJSON_Delete(jsonMsg);
cJSON_Delete(jsonRes);
cJSON是一個非常不錯的庫,簡單而整潔,但是需要了解一些事情:
cJSON_GetObjectItem(command,"param1")->valuestring
在此示例中進行分析后為char *
。
由於您將其替換為"new value 1"
(即const char *
,因此在刪除jsonMsg
,delete命令將嘗試釋放該const char *
,從而導致分段錯誤。
有兩種方法:
char* jsonStr = "{ \"command\" : { \"param1\": \"value1\", \"param2\": \"value2\" } }";
cJSON *jsonMsg = cJSON_Parse(jsonStr);
cJSON *command = CJSON_GetObjectItem(jsonMsg, "command");
直到這里,
然后是一個簡單的命令:
cJSON_ReplaceItemInObject(command,"param1", cJSON_CreateString("new value 1"));
和完成:
cJSON_Print(jsonMsg);
cJSON_Delete(jsonMsg);
要么
cJSON_DeleteItemFromObject(command,"param1");
cJSON_AddItemToObject(command,"param1",cJSON_CreateString("new value 1"));
要么
如果您堅持手動操作,那么可以:
free(cJSON_GetObjectItem(command,"param1")->value string);
cJSON_GetObjectItem(command,"param1")->valuestring=strdup("new value 1");
但是如果您手動操作,則應在嘗試type cJSON_IsReference
之前檢查type cJSON_IsReference
,其次strdup
將分配新內存以復制“新值1”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.