Ubuntu 20.04下读取JSON转nlohmann::json对象随机崩溃问题求助
问题根因分析
你当前遇到的随机崩溃和异常未捕获问题核心由以下几个常见错误导致:
- 跨进程同步失效:普通
std::mutex仅支持同进程内的线程同步,若读写逻辑运行在两个独立进程中,这把锁完全不生效,会导致写进程截断文件后尚未写入完整内容时,读进程就读取到残缺/空的非法JSON内容,部分版本的nlohmann_json遇到严重非法输入时会直接终止程序而非抛出异常。 - 锁使用不安全:手动调用
lock()/unlock()时,若try块内加锁后、解锁前抛出异常,锁将永久无法释放,触发死锁后后续所有读写操作都会异常。 - 边界校验缺失:文件打开未做成功判断、JSON字段访问未做存在性和类型校验、异常捕获范围过窄,都会导致意料外的崩溃。
- 直接截断写原文件的机制本身不安全:写文件过程中程序崩溃或被中断会生成损坏的JSON文件,后续读操作必然失败。
可行修正建议
- 替换同步机制适配使用场景:如果是多进程读写场景,将普通
std::mutex替换为跨进程同步方案,可选fcntl文件锁、设置了PTHREAD_PROCESS_SHARED属性的共享内存mutex、或者原子pid文件锁;如果是同进程多线程场景,保留原mutex但改用RAII锁守卫:// 替换手动lock/unlock,离开作用域自动释放锁,避免异常导致的锁泄露 std::lock_guard<std::mutex> guard(mLock); - 优化写文件逻辑为原子写入:
// 写临时文件后原子替换原文件,永远不会生成损坏的中间文件 std::string tmpPath = std::string(<filepath>) + ".tmp"; std::ofstream out(tmpPath); if (out.is_open()) { out << jWriteObj << std::flush; out.close(); rename(tmpPath.c_str(), <filepath>); } - 补全所有边界校验和异常捕获:
- 所有文件打开操作后校验
is_open()返回值,打开失败直接返回默认值或错误 - 解析JSON前先读取完整文件内容到字符串,再调用parse接口解析,设置解析不直接终止的参数:
std::string buf((std::istreambuf_iterator<char>(fileDesc)), std::istreambuf_iterator<char>()); // 第三个参数为false表示解析失败抛异常,不直接终止程序 jReadObj = nlohmann::json::parse(buf, nullptr, false); - 扩展异常捕获范围,追加std::exception和兜底捕获:
catch (const nlohmann::json::exception& e) { std::cout << "JSON exception: " << e.what() << std::endl; } catch (const std::exception& e) { std::cout << "System exception: " << e.what() << std::endl; } catch (...) { std::cout << "Unknown exception" << std::endl; } - 访问JSON字段前先校验存在性和类型:
if (jReadObj.contains(flagName) && jReadObj[flagName].is_boolean()) { flagValue = jReadObj[flagName].get<bool>(); }
- 所有文件打开操作后校验
- 修复现有代码的语法错误:将
std:string改为std::string,读文件用的istream改为std::ifstream,open时传入正确的文件路径参数。
内容的提问来源于stack exchange,提问作者Harish
相关产品推荐
相关产品推荐

