Delphi 10.4.1环境下JSON操作代码出现内存泄漏求错误排查
Delphi 10.4 JSON代码内存泄漏问题排查结果
代码中存在的两个核心错误
- 子JSON对象无异常保护导致泄漏
你在oResultJO的try块内直接创建oSecondJO、oFirstJO两个对象,没有配套的异常处理逻辑。如果oSecondJO创建成功后,oFirstJO创建或后续代码抛出异常,已经创建的oSecondJO/oFirstJO没有释放逻辑,会直接泄漏。 - 重复添加同名字段存在泄漏风险
连续两次给oFirstJO添加TYPE_1字段:- 当
TJSONObject.Duplicates为默认值dupAccept时,会保留两个同名字段,虽然不会直接泄漏,但不符合JSON标准,多数第三方JSON解析库只会读取最后一个同名字段的值,属于不规范写法。 - 当
TJSONObject.Duplicates设置为dupReplace时,添加第二个同名字段会直接覆盖旧字段,且旧的TJSONNumber(1)实例以及对应的TJSONPair不会被自动释放,直接造成内存泄漏。
- 当
修正后的代码示例
oResultJO := TJSONObject.Create; try oSecondJO := nil; oFirstJO := nil; try oSecondJO := TJSONObject.Create; oFirstJO := TJSONObject.Create; // 先删除已存在的同名字段再添加,避免重复键问题 var oOldPair := oFirstJO.RemovePair('TYPE_1'); if Assigned(oOldPair) then oOldPair.Free; oFirstJO.AddPair('TYPE_1', TJSONNumber.Create(1)); // 如确实需要保留重复键请注释上述删除逻辑,恢复第二条添加代码 // oFirstJO.AddPair('TYPE_1', TJSONNumber.Create(2)); oSecondJO.AddPair('TYPE_2', TJSONNumber.Create(3)); if oFirstJO.Count > 0 then begin oResultJO.AddPair('FIRST', oFirstJO); oFirstJO := nil; // 交给父对象管理后置空,避免重复释放 end; if oSecondJO.Count > 0 then begin oResultJO.AddPair('SECOND', oSecondJO); oSecondJO := nil; // 交给父对象管理后置空,避免重复释放 end; ShowMessage(oResultJO.ToString); finally // 统一释放未交给父对象的资源 oFirstJO.Free; oSecondJO.Free; end; finally oResultJO.Free; end;
修正逻辑说明
- 给子对象创建逻辑增加独立的
try-finally块,所有未交给父对象oResultJO的子对象统一在finally块释放,避免异常场景下的泄漏。 - 添加同名字段前先调用
RemovePair删除旧字段并手动释放,既符合JSON规范,也避免重复键场景下的泄漏。 - 子对象交给父对象管理后立即将变量置空,避免后续重复释放。
内容的提问来源于stack exchange,提问作者Peter Jones
相关产品推荐
相关产品推荐

