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
相关产品推荐
相关产品推荐

