fast json 引起得内存泄漏

在进行压力测试时,发现系统性能迅速下降,TPS降低,最终导致系统崩溃。进一步调查发现,CPU占用率极高,GC线程过度活跃,且存在内存泄漏问题。深入分析后,确认内存泄漏与FastJSON中IdentityHashMap处理ResolvableType类型有关。

最近项目在做压力测试得时候,发现性能快速劣化,tps很低,到最后系统挂死。

通过查看cpu情况,发现cpu占用非常高,找到暂用cpu的线程是gc线程

同时查看系统内存gc情况,发现频繁gc,并且内存不能够回收,

明显是有了内存泄漏的现象,再dump内存工具,发现com.alibaba.fastjson.util.IdentityHashMap产生了大量

org.springframework.core.ResolvableType

通过分析代码

主要原因是IdentityHashMap 使用 System.identityHashCode作为key,而没有使用 ResolvableType的hash值

 

 

   

 

     主要的出现场景就是json解析的时候,采用了泛型类,泛型类又没有直接指定具体的类型

 

{"date":"20250521110514","plcType":"01","electricityMeter":{},"offset":"01","data":{"01":{"10":{"CE85":{"20":{"03":"%DBX42.3.3"},"05":{"03":"%DBX50.8.4"}}},"20":{"CE84":{"20":{"03":"%DBX42.1.3"},"05":{"03":"%DBX50.6.4"}},"CE83":{"20":{"03":"%DBX42.3.0"},"53":{"03":"%DBX50.8.1"}},"CE82":{"20":{"03":"%DBX42.1.0"},"05":{"03":"%DBX50.6.1"}},"A902":{"17":{"03":"%DBX50.12.6"},"18":{"03":"%DBX50.22.6"},"A5":{"03":"%DBX50.23.2"},"05":{"03":"%DBX50.9.1"}},"CE81":{"20":{"03":"%DBX42.3.0"},"53":{"03":"%DBX50.8.0"}},"CE80":{"20":{"03":"%DBX42.1.0"},"53":{"03":"%DBX50.6.0"}},"A901":{"17":{"03":"%DBX50.10.6"},"18":{"03":"%DBX50.20.6"},"A5":{"03":"%DBX50.21.2"},"05":{"03":"%DBX50.7.1"}},"C601":{"11":{"03":"%DBX42.5.5"},"12":{"03":"%DBX42.5.6"},"13":{"03":"%DBX42.5.7"},"14":{"02":"%DBD81.212"},"15":{"02":"%DBD81.216"},"16":{"02":"%DBD81.220"},"17":{"02":"%DBD81.200"},"18":{"02":"%DBD81.204"},"19":{"02":"%DBD81.208"},"21":{"02":"%DBD100.140"},"22":{"02":"%DBD100.136"},"23":{"02":"%DBD100.132"},"24":{"03":"%DBX50.36.2"},"25":{"03":"%DBX50.36.1"},"26":{"03":"%DBX50.36.0"},"27":{"03":"%DBX50.46.2"},"28":{"03":"%DBX50.46.1"},"29":{"03":"%DBX50.46.0"},"61":{"02":"%DBD100.124"},"62":{"02":"%DBD100.120"},"63":{"02":"%DBD100.116"},"D2":{"03":"%DBX50.35.5"},"D3":{"03":"%DBX50.45.5"},"D6":{"03":"%DBX50.35.4"},"D7":{"03":"%DBX50.45.4"},"DA":{"03":"%DBX50.35.3"},"DB":{"03":"%DBX50.45.3"}}},"30":{"C301":{"55":{"03":"%DBX41.1.1"},"56":{"03":"%DBX41.1.0"},"60":{"03":"%DBX45.4.3"},"CE":{"03":"%DBX50.5.2"}},"CE90":{"20":{"03":"%DBX42.3.2"},"53":{"03":"%DBX50.8.3"}},"E001":{"11":{"03":"%DBX50.20.2"},"12":{"03":"%DBX50.10.2"},"17":{"02":"%DBD100.0"},"19":{"03":"%DBX50.31.1"},"25":{"02":"%DBD100.16"},"30":{"02":"%DBD81.24"},"31":{"02":"%DBD81.28"},"32":{"02":"%DBD81.32"},"33":{"02":"%DBD81.72"},"34":{"02":"%DBD81.76"},"35":{"02":"%DBD81.80"},"36":{"02":"%DBD81.96"},"37":{"02":"%DBD81.100"},"39":{"02":"%DBD81.104"},"55":{"03":"%DBX42.2.0"},"56":{"02":"%DBD100.28"},"57":{"02":"%DBD100.36"},"58":{"02":"%DBD81.224"},"62":{"02":"%DBD100.32"},"65":{"02":"%DBD100.44"},"87":{"03":"%DBX50.30.7"},"88":{"03":"%DBX50.40.7"},"01":{"02":"%DBD100.24"},"03":{"02":"%DBD100.8"},"04":{"02":"%DBD100.40"},"05":{"02":"%DBD100.20"},"06":{"02":"%DBD100.4"},"07":{"02":"%DBD100.12"},"A0":{"03":"%DBX50.10.4"},"A1":{"03":"%DBX50.20.4"},"E6":{"03":"%DBX50.31.0"},"E7":{"03":"%DBX50.41.0"},"AE":{"03":"%DBX50.30.5"},"AF":{"03":"%DBX50.40.5"},"F6":{"02":"%DBD81.8"},"B2":{"03":"%DBX50.30.1"},"F7":{"02":"%DBD81.4"},"B3":{"03":"%DBX50.40.1"},"F8":{"02":"%DBD81.0"},"1E":{"03":"%DBX50.6.5"},"B6":{"03":"%DBX50.30.0"},"B7":{"03":"%DBX50.40.0"},"B8":{"03":"%DBX50.11.1"},"BB":{"03":"%DBX50.41.1"},"BE":{"03":"%DBX50.30.2"},"BF":{"03":"%DBX50.40.2"},"C2":{"03":"%DBX50.30.3"},"C3":{"03":"%DBX50.40.3"},"C9":{"03":"%DBX50.21.3"},"CE":{"03":"%DBX50.5.0"},"3B":{"03":"%DBX50.21.1"}}},"40":{"E101":{"61":{"02":"%DBD100.112"},"62":{"02":"%DBD100.108"},"63":{"02":"%DBD100.104"},"A2":{"03":"%DBX50.35.6"},"01":{"02":"%DBD100.128"},"CE":{"03":"%DBX45.4.1"},"D6":{"03":"%DBX50.35.1"},"D7":{"03":"%DBX50.45.1"},"DA":{"03":"%DBX50.35.0"},"DB":{"03":"%DBX50.45.0"},"D2":{"03":"%DBX50.35.2"},"D3":{"03":"%DBX50.45.2"}},"E002":{"11":{"03":"%DBX50.22.2"},"12":{"03":"%DBX50.12.2"},"17":{"02":"%DBD100.56"},"19":{"03":"%DBX50.33.1"},"25":{"02":"%DBD100.72"},"30":{"02":"%DBD81.84"},"31":{"02":"%DBD81.88"},"32":{"02":"%DBD81.92"},"33":{"02":"%DBD81.12"},"34":{"02":"%DBD81.16"},"35":{"02":"%DBD81.20"},"36":{"02":"%DBD81.36"},"37":{"02":"%DBD81.40"},"39":{"02":"%DBD81.44"},"55":{"03":"%DBX42.4.0"},"56":{"02":"%DBD100.84"},"57":{"02":"%DBD100.92"},"58":{"02":"%DBD81.228"},"62":{"02":"%DBD100.88"},"65":{"02":"%DBD100.100"},"87":{"03":"%DBX50.32.7"},"88":{"03":"%DBX50.42.7"},"01":{"02":"%DBD100.80"},"03":{"02":"%DBD100.64"},"04":{"02":"%DBD100.96"},"05":{"02":"%DBD100.76"},"06":{"02":"%DBD100.60"},"07":{"02":"%DBD100.68"},"A0":{"03":"%DBX50.12.4"},"A1":{"03":"%DBX50.22.4"},"E6":{"03":"%DBX50.33.0"},"E7":{"03":"%DBX50.43.0"},"AE":{"03":"%DBX50.32.5"},"AF":{"03":"%DBX50.42.5"},"F6":{"02":"%DBD81.68"},"B2":{"03":"%DBX50.32.1"},"F7":{"02":"%DBD81.64"},"B3":{"03":"%DBX50.42.1"},"F8":{"02":"%DBD81.60"},"1E":{"03":"%DBX50.8.5"},"B6":{"03":"%DBX50.32.0"},"B7":{"03":"%DBX50.42.0"},"B8":{"03":"%DBX50.13.1"},"BB":{"03":"%DBX50.43.1"},"BE":{"03":"%DBX50.32.2"},"BF":{"03":"%DBX50.42.2"},"C2":{"03":"%DBX50.32.3"},"C3":{"03":"%DBX50.42.3"},"C9":{"03":"%DBX50.23.3"},"CE":{"03":"%DBX50.5.1"},"3B":{"03":"%DBX50.23.1"}},"CE8F":{"20":{"03":"%DBX42.1.2"},"53":{"03":"%DBX50.6.3"}},"E301":{"55":{"03":"%DBX41.1.4"},"CE":{"03":"%DBX50.5.3"}},"E202":{"17":{"02":"%DBW82.2"},"53":{"03":"%DBX50.4.1"},"55":{"03":"%DBX82.20.2"},"58":{"02":"%DBD81.236"},"A1":{"03":"%DBX50.24.3"},"A2":{"03":"%DBX50.34.3"},"01":{"02":"%DBD100.148"},"03":{"02":"%DBW82.30"}}},"50":{"CE8E":{"20":{"03":"%DBX42.3.1"},"53":{"03":"%DBX50.8.2"}},"E401":{"18":{"02":"%DBD100.52"},"A1":{"03":"%DBX50.24.0"},"1A":{"03":"%DBX50.23.7"},"A2":{"03":"%DBX50.34.0"},"1B":{"03":"%DBX50.33.7"},"01":{"02":"%DBD100.48"}},"CE8D":{"20":{"03":"%DBX42.1.1"},"53":{"03":"%DBX50.6.2"}},"CE8C":{"20":{"03":"%DBX42.5.4"}},"CE8B":{"20":{"03":"%DBX42.5.3"}},"CE8A":{"20":{"03":"%DBX42.5.2"}},"CE89":{"20":{"03":"%DBX42.5.1"}},"CE88":{"20":{"03":"%DBX42.5.0"}},"CE87":{"20":{"03":"%DBX42.3.4"},"53":{"03":"%DBX50.9.2"}},"CE86":{"20":{"03":"%DBX42.1.4"},"53":{"03":"%DBX50.7.2"}}}},"02":{"15":{"E302":{"40":{"03":"%DBX45.2.6"}},"A801":{"40":{"03":"%DBX45.2.0"}},"D803":{"11":{"03":"%DBX45.5.0"},"12":{"03":"%DBX45.5.1"}},"D802":{"CE":{"03":"%DBX45.4.0"}}},"25":{"D801":{"40":{"03":"%DBX45.2.7"}},"C601":{"CE":{"03":"%DBX45.4.2"}},"E001":{"40":{"03":"%DBX45.2.1"}},"E002":{"40":{"03":"%DBX45.2.2"}},"E101":{"40":{"03":"%DBX45.3.2"}},"C301":{"40":{"03":"%DBX45.2.3"}},"E301":{"40":{"03":"%DBX45.2.5"}}}},"null":{"16":{"D804":{"37":{"03":"%DBX50.0.0"}},"E302":{"55":{"03":"%DBX41.1.5"},"CE":{"03":"%DBX50.5.4"}}},"24":{"E201":{"16":{"02":"%DBD82.10"},"17":{"02":"%DBD82.6"},"53":{"03":"%DBX50.4.0"},"55":{"03":"%DBX82.60.2"},"58":{"02":"%DBD81.232"},"A1":{"03":"%DBX50.24.2"},"A2":{"03":"%DBX50.34.2"},"01":{"02":"%DBD100.144"},"03":{"02":"%DBD82.64"}}}}},"aLen":6132,"id":"365","type":"5","frequency":"10"} 我有以上一个json文件,使用我提供代码中的JsonAnalysis()函数进行解析,使用的是Linux mcuzone 3.10.101 开发板跑程序,系统出现malloc(): memory corruption (fast): 0x01575298 ***错误,请根据提供的代码具体分析查找问题
最新发布
11-22
<think> 我们面对的问题是:在Linux mcuzone 3.10.101开发板上,使用JsonAnalysis()函数解析给定的JSON文件时,出现了'malloc(): memory corruption (fast)'错误。这个错误通常表示在动态内存分配时发生了内存损坏,比如缓冲区溢出、使用已经释放的内存、或者重复释放内存等。 根据提供的引用[1],我们知道json-c库在使用不当时可能导致内存泄漏和踩内存问题。引用[1]特别指出,问题往往源于不清楚某些接口的用法。另外,引用[3]提到了在arm-linux下交叉编译json-c-0.9库时遇到编译问题,这提示我们可能涉及到交叉编译环境的问题。 下面,我们将逐步分析可能的原因: ### 1. **内存溢出(Buffer Overflow)** - 在解析JSON时,如果某个字符串值或数组元素超出了预分配的内存空间,就会覆盖相邻的内存区域,导致内存损坏。json-c库在解析过程中会动态分配内存,如果JSON结构异常(如非常长的字符串或嵌套很深),可能触发此问题。 - 检查JSON文件是否有异常结构,比如特别长的字符串或者特别深的嵌套。 ### 2. **使用已释放的内存(Use After Free)** - 在json-c库中,当我们释放了一个JSON对象后,如果再次使用它,就会导致未定义行为。例如,在解析过程中,如果某个JSON对象被提前释放,而后续又试图访问它,可能导致内存损坏。 - 检查代码中是否有提前释放JSON对象的情况。 ### 3. **重复释放(Double Free)** - 如果同一个JSON对象被释放了两次,也会导致内存损坏。json-c库中的`json_object_put`函数会减少对象的引用计数,当引用计数为0时释放对象。如果对一个对象多次调用`json_object_put`,就会导致重复释放。 - 确保每个`json_object_put`调用都是针对有效的对象,并且每个对象只释放一次。 ### 4. **多线程问题** - 如果程序在多线程环境中调用json-c库的函数,而json-c库的某些版本不是线程安全的,则可能导致内存损坏。确保在多线程环境中正确使用json-c库。 ### 5. **交叉编译环境问题** - 引用[3]提到在arm-linux下交叉编译json-c-0.9库时遇到问题。开发板是arm架构,所以可能使用了交叉编译的json-c库。如果交叉编译时配置不正确,可能导致库的行为异常。比如,编译选项不匹配,或者使用了不兼容的编译器版本。 - 确保交叉编译时使用的配置与目标平台兼容,特别是内存对齐和字节序等问题。 ### 6. **JSON文件格式问题** - 虽然引用[2]提到JSON应该是格式正确的,但实际文件可能有错误。例如,未转义的特殊字符、不匹配的括号等。json-c库在解析格式错误的JSON时可能行为异常,导致内存损坏。 - 使用JSON验证工具检查JSON文件的正确性。 ### 7. **json-c库的已知问题** - 引用[1]指出json-c的0.12.1版本存在一些用法问题。因此,需要检查代码中是否遵循了正确的API使用方式。例如: - 使用`json_object_to_json_string`返回的字符串是内部缓冲区,不应被修改,且在下一次调用该函数时可能会被覆盖。 - 使用`json_object_put`来释放对象,而不是直接使用`free`。 - 检查代码中是否正确管理了JSON对象的生命周期。 ### 8. **堆损坏(Heap Corruption)** - 这个错误也可能是由于程序其他部分的内存错误导致的,比如在JSON解析之前或之后,程序其他部分发生了内存越界写操作,破坏了堆的结构。因此,问题可能并不直接在于json-c库,而是程序其他部分的问题。 ### 分析步骤建议: 1. **检查JSON文件**:确保JSON文件格式正确,没有过于复杂或异常的结构。 2. **检查代码**:仔细审查`JsonAnalysis()`函数,确保: - 每个`json_object_get`都有对应的`json_object_put`。 - 没有对同一个对象多次调用`json_object_put`。 - 没有使用已释放的对象。 - 字符串操作没有越界。 3. **使用内存调试工具**:在开发板上运行程序时,可以使用Valgrind(如果可用)来检测内存问题。但由于开发板资源有限,可能需要在模拟环境中运行。 4. **简化测试**:尝试用最小的JSON文件测试,逐步增加复杂度,定位问题。 5. **检查json-c版本**:确认使用的json-c版本,并查看该版本是否存在已知的内存问题。考虑升级到较新版本(如果可能)。 由于开发板资源有限,可能无法使用Valgrind等工具,因此需要仔细检查代码和JSON文件的结构,并确保json-c库正确编译。 ### 引用说明 根据提供的引用[1][3],json-c库的使用和交叉编译配置可能是关键因素。请确保按照正确的API使用方式,并检查交叉编译的配置是否合理[^1][^3]。 §§相关问题§§ 1. 如何检测JSON文件格式的正确性? 2. 在嵌入式环境中如何调试内存损坏问题? 3. json-c库中如何正确管理JSON对象的生命周期? </think> 根据您提供的错误信息 `malloc(): memory corruption (fast): 0x01575298`,结合引用内容中关于json-c内存问题的分析,以下是可能的原因及具体分析: ### 一、核心原因分析 1. **内存越界访问(主要嫌疑)** `malloc()` 内存损坏通常由**缓冲区溢出**或**非法指针访问**引起。在解析JSON时,可能出现: - 字符串值未正确终止:若JSON包含未转义的特殊字符(如`"`、`\`),解析时可能越过预分配边界 - 数组索引越界:嵌套数组/对象层级超出预期,导致访问非法内存区域 - 结构体对齐问题(ARM架构敏感):引用[3]的交叉编译问题可能引发内存对齐错误 2. **对象生命周期管理错误** 引用[1]明确指出:json-c的 **`json_object_put()` 使用不当** 是内存问题的常见根源: ```c // 错误示例:重复释放 json_object* obj = json_object_new_string("test"); json_object_put(obj); // 第一次释放 json_object_put(obj); // 二次释放导致内存损坏(fastbin检测) ``` 3. **跨平台兼容性问题** 开发板环境 `Linux mcuzone 3.10.101` (ARM架构) 可能存在: - 字节序差异(Big/Little Endian) - 结构体填充(padding)不一致 - 堆内存分配器行为差异(如ptmalloc vs. dlmalloc) ### 二、具体诊断步骤 1. **验证JSON格式合法性** 使用引用[2]推荐的命令行工具验证: ```bash # 安装jq工具 sudo apt-get install jq # 检测JSON文件 jq . your_file.json ``` 特殊关注:非ASCII字符、未闭合括号、非法转义符 2. **检查内存操作代码** 重点排查以下模式: ```c // 高危操作1:直接操作json_object内部指针 char* str = json_object_get_string(obj); // 返回指针不可修改! str[0] = 'a'; // 将破坏内存结构 // 高危操作2:未检查类型直接转换 json_object_object_get_ex(obj, "key", &tmp); int val = json_object_get_int(tmp); // 若tmp非int类型将导致越界 ``` 3. **交叉编译配置检查** 参考引用[3]的编译参数,确认: - 使用 `--host=arm-linux` 明确指定目标架构 - 启用内存调试选项: ```bash CFLAGS="-fsanitize=address -D_FORTIFY_SOURCE=2" \ ./configure --prefix=/your/path --host=arm-linux ``` ### 三、解决方案建议 1. **紧急规避措施** 在 `JsonAnalysis()` 入口添加内存校验: ```c #include <mcheck.h> void JsonAnalysis() { mtrace(); // 启用内存跟踪 // ... 原解析代码 ... muntrace(); } ``` 运行后生成日志,使用 `mtrace` 工具分析 2. **长期修复方案** - **引用计数审计**:确保每个 `json_object_new_*()` 都有且仅有一个 `json_object_put()` - **安全访问封装**: ```c // 安全获取字符串值 char* safe_get_string(json_object* obj, const char* key) { json_object* tmp; if (json_object_object_get_ex(obj, key, &tmp) && json_object_is_type(tmp, json_type_string)) { return strdup(json_object_get_string(tmp)); // 复制独立副本 } return NULL; } ``` 3. **平台适配增强** 在ARM开发板初始化时添加: ```c #include <json-c/json_object_private.h> void json_c_mem_set_hooks( void*(*malloc_fn)(size_t), void(*free_fn)(void*) ); // 替换为开发板兼容的内存分配器 ### 四、根本原因定位流程图 ```mermaid graph TD A[发生 malloc corruption] --> B{检查JSON文件} B -->|格式错误| C[修复JSON语法] B -->|格式正确| D{检查对象操作} D --> E[引用计数错误] --> E1[重复释放/泄漏] D --> F[类型转换错误] --> F1[强制转换非字符串] D --> G[内存对齐问题] --> G1[ARM结构体填充差异] G1 --> H[重新配置交叉编译参数] E1 --> I[添加引用计数日志] ``` > 建议优先使用 **Valgrind for ARM** 交叉编译版本进行堆内存分析(需在开发板部署),可精确定位到具体越界代码位置[^1][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值