修改通过分析字符串文字创建的cJSON结构时出现分段错误

修改通过分析字符串文字创建的cJSON结构时出现分段错误,c,cjson,C,Cjson,当使用cJSON解析字符串文字时,我在释放cJSON结构时遇到了一个分段错误 原代码如下: char* jsonStr = "{ \"command\" : { \"param1\": \"value1\", \"param2\": \"value2\" } }"; cJSON *jsonMsg = cJSON_Parse(jsonStr); cJSON *command = CJSON_GetObjectItem(jsonMsg, "command"); cJSON_GetObjectItem

当使用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
char*jsonStr=“{\'command\':{\'param1\':\'value1\',\'param2\':\'value2\'}”;
cJSON*jsonMsg=cJSON_Parse(jsonStr);
cJSON*command=cJSON_GetObjectItem(jsonMsg,“命令”);
cJSON_GetObjectItem(命令,“param1”)->valuestring=“新值1”;

cJSON_Delete(jsonMsg);// 当我第一次遇到这种情况时,我对这种行为感到困惑。该示例与cJSON中的示例非常相似

我第一次尝试的解决方案是设置“param1”的类型,这样cJSON_Delete()函数就不会试图释放内存。也就是说,在cJSON->type成员中设置“cJSON\u 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()导致的孤立内存malloc’d而导致的内存泄漏

最终的代码如下所示:

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
在本例中解析后,是一个
字符*

由于将其替换为
“新值1”
,即
常量字符*
,因此在删除
jsonMsg
时,delete命令会尝试释放该
常量字符*
,从而导致分段错误

有两种方法:

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"));

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");

但如果你手动操作,在尝试释放之前,应该检查<代码>类型CjSuniISCORMUCT/<代码>,其次,<代码> StrudU/SCOR>将分配新的内存来复制“新值1”。

这看起来像C,而不是C++。请删除不相关语言的标记。你的问题不完整。提供一个解决方案。您需要避免编辑器引入Unicode代码
(U+201C)和
(U+201D)来代替
(U+0022);编译器不太喜欢它们。