You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

cJSON_Delete()调用致应用崩溃问题排查及cJSON变量复用疑问

cJSON_Delete()调用致应用崩溃问题排查及cJSON变量复用疑问

Hey there, let's break down exactly what's happening here and clear up your confusion around reusing cJSON variables.

问题根源:双重释放内存

The crash you're seeing is 100% caused by double-freeing memory when you add the same cjTimeZone cJSON object to two different parent objects (cjStart and cjEnd). Here's why:

When you call cJSON_AddItemToObject(), cJSON takes ownership of the child object you pass in. That means when you later call cJSON_Delete(cjMsg), it will recursively traverse all child objects and free their memory.

In your code:

  1. You create cjTimeZone once with cJSON_CreateString(TZ)
  2. You add it to cjStart
  3. You then add the same exact pointer to cjEnd

When cJSON_Delete() processes cjStart, it frees cjTimeZone. Then when it gets to cjEnd, it tries to free that same pointer again—this is a classic double-free bug, which almost always causes a crash.

为什么复用cjDateTime没出问题?

You mentioned reusing cjDateTime didn't cause issues, but let's look at what you actually did there:

strcpy(dateStr, "2025-06-01T14:00:00");
cjDateTime = cJSON_CreateString(dateStr); // 创建新对象,分配新内存
cJSON_AddItemToObject(cjStart, "dateTime", cjDateTime);

strcpy(dateStr, "2025-06-01T15:00:00");
cjDateTime = cJSON_CreateString(dateStr); // 再次创建新对象,指向不同内存
cJSON_AddItemToObject(cjEnd, "dateTime", cjDateTime);

你其实并没有复用同一个cJSON对象——只是复用了指针变量,但每次调用cJSON_CreateString()时,都会在内存中分配一个全新的cJSON对象。旧的cjDateTime指针已经交给cjStart(并由它接管所有权),所以覆盖指针变量并不会影响已有的对象,这就是为什么没有崩溃的原因。

正确的解决方案

针对cjTimeZone的问题,你有两种可行的修复方式:

  1. 创建两个独立的cJSON字符串对象,就像你用cjDateTime2那样:

    cjTimeZone = cJSON_CreateString(TZ);
    cJSON_AddItemToObject(cjStart, "timeZone", cjTimeZone);
    
    cJSON *cjTimeZone2 = cJSON_CreateString(TZ);
    cJSON_AddItemToObject(cjEnd, "timeZone", cjTimeZone2);
    

    这种方式简单安全——每个父对象都拥有自己的字符串对象副本,不会出现双重释放的问题。

  2. 使用引用计数(如果你的cJSON版本支持)
    一些较新的cJSON版本提供了cJSON_Duplicate()或引用计数相关函数。如果你想复用同一个对象而不复制它,可以在添加到第二个父对象前增加它的引用计数。但对于这种简单字符串,直接复制通常更简单且不易出错。

关于cJSON变量复用的核心规则

为了避免未来再出现这类崩溃,记住这几条黄金规则:

  • 永远不要将同一个cJSON对象指针添加到多个父对象中——每次添加都会转移所有权,当父对象被删除时,该对象会被多次释放。
  • 复用指针变量是没问题的,但复用实际的cJSON对象(它指向的内存)不行,除非你显式处理引用计数或复制对象。
  • 务必牢记:cJSON_AddItemTo*系列函数会接管子对象的所有权——你之后不能自己释放它,也不能将它传递给另一个添加函数。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 09:33:00