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

Json11对象在ThreadPool线程中因原函数返回失效崩溃问题求助

问题:Json11对象在线程池中的生命周期崩溃问题

我使用开源Json库Json11解析Json字符串,将解析后的对象传入线程池处理。add_to_pool()函数接收Json字符串,调用parse()生成json_object,遍历其层级结构后,将数组元素的地址传入线程池工作项,提交至ThreadPool执行thread_func()。

若add_to_pool()先于thread_func()执行完毕并返回,线程中访问的data会变为无效指针,导致程序崩溃。我尝试新建对象指向原对象,但新对象仍与原对象指向同一内存地址。现咨询:C++中是否存在现成解决方法,还是需手动编写深拷贝函数复制整个Json对象?

相关代码

add_to_pool()函数

void add_to_pool(std::string json_string) {
    std::string err;
    json11::Json json_object = json11::Json::parse(json_string.c_str(), err);

    for (auto it : json_object.object_items()) {
        for (auto ait : it.second.array_items()) {
            PTP_WORK work_item = CreateThreadpoolWork((PTP_WORK_CALLBACK)thread_func, &ait, &tp_env);
            SubmitThreadpoolWork(work_item);
        }
    }
}

thread_func()函数

void thread_func(PTP_CALLBACK_INSTANCE instance, json11::Json data, PTP_WORK work) {
    for (auto key: data.object_items()) {
        std::cout << key.first << ":" << key.second.string_value() << "\n";
    }
}

示例Json结构

{
    "first_layer": {
        "second_layer": [
            {
                "key":"value",
                "yes":"no"
            },
            {
                "example":"here"
            }
        ]
    }
}

解决方案

问题根源

Json11的Json类采用值语义+内部共享指针的实现:默认拷贝是浅拷贝,多个Json对象共享同一块底层数据内存。当add_to_pool()返回时,局部变量json_object被销毁,底层共享数据的引用计数降至0后会被释放,此时线程再访问就会触发野指针崩溃。

现成解决方法:利用Json11自带的深拷贝能力

Json11内置了clone()方法,可生成完全独立的Json对象副本,底层数据不与原对象共享。结合智能指针管理副本生命周期,就能彻底解决问题:

修改后的add_to_pool()

#include <memory>

void add_to_pool(std::string json_string) {
    std::string err;
    json11::Json json_object = json11::Json::parse(json_string.c_str(), err);

    for (auto it : json_object.object_items()) {
        for (auto ait : it.second.array_items()) {
            // 深拷贝生成独立的Json对象,用shared_ptr托管生命周期
            auto json_copy = std::make_shared<json11::Json>(ait.clone());
            
            // 将shared_ptr指向的对象地址传入线程池
            PTP_WORK work_item = CreateThreadpoolWork(
                reinterpret_cast<PTP_WORK_CALLBACK>(thread_func),
                json_copy.get(),
                &tp_env
            );
            
            SubmitThreadpoolWork(work_item);
        }
    }
}

修改后的thread_func()

void thread_func(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) {
    // 将传入的指针重新包装为shared_ptr,延续对象生命周期
    std::shared_ptr<json11::Json> data_ptr(static_cast<json11::Json*>(context));
    const json11::Json& data = *data_ptr;

    for (auto& key : data.object_items()) {
        std::cout << key.first << ":" << key.second.string_value() << "\n";
    }

    // 销毁线程池工作项
    CloseThreadpoolWork(work);
}

为什么不用手动深拷贝?

手动遍历Json对象的所有层级实现深拷贝不仅繁琐,还容易遗漏嵌套结构(比如数组、嵌套对象),出错概率高。Json11的clone()方法已经封装了完整的深拷贝逻辑,直接调用即可,高效且可靠。

关键注意事项

  • 禁止直接传递局部变量地址:循环中的ait是局部变量,生命周期仅在当前循环迭代内,即使原json_object未销毁,循环结束后ait也会失效。
  • 智能指针是核心:shared_ptr会自动维护引用计数,确保线程执行期间副本不会被释放,函数执行完毕后自动清理内存。

内容的提问来源于stack exchange,提问作者Jahnoh44

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 13:30:35