SDDC-SDK 库内存泄露导致ESP32收不到任何报文记录以及修复,附带cjson可能导致内存泄露的情况
2022/4/14 7:14:56
本文主要是介绍SDDC-SDK 库内存泄露导致ESP32收不到任何报文记录以及修复,附带cjson可能导致内存泄露的情况,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
项目场景:
之前为了方便 SDDC 协议使用,我自己写了一个 SDDC 的 SDK, 具体详见:同人逼死官方系列!基于sddc 协议的SDK框架 sddc_sdk_lib 解析 和 同人逼死官方系列 从 DDC 嗅探器到 sddc_sdk_lib 的数据解析 ,但是当时对 cjson 的使用还不是很熟悉,导致出现了一个内存泄露的问题,导致了ESP32运行一段时间后无法收到报文。
问题描述
在频繁收到消息命令,调用 sddc_on_message_lib 函数后,大概半小时左右 ESP32 将会收不到任何报文,通过打印发现 select 一直返回 0 ,这个问题一度让我非常费解。
网上最多的回答是 FD_SET 没有重置导致的,可是我检查了 sddc 代码,官方确实做了循环调用 FD_SET ,没有问题,不是这个原因。
射频信号确实发出来了。
ESP32底层也不应该有问题。
当时出现问题的是一个 I2C设备。导致我一直在怀疑是 I2C 导致的问题,别说还真有可能,ESP32 的 I2C 有可能会受到干扰 I2C 《 调试经验分享》然后我苦兮兮的去检测 I2C ,发现也是正常的。这就很令人费解了啊。
最后我无意中发现另外一个 通过 GPIO 读取数据的设备在长时间运行后也出现这样的问题。我对比了这两个设备和其他没问题的设备,最后发现差异在触发 "get" 命令的频率上,而 "get" 是一个命令,会触发消息处理回调函数,这样我才把注意力调到了回调处理流程上,然后发现了一处内存泄漏  ̄□ ̄||。
原因分析:
内存泄露位于 SDDC_SDK_lib.c 中的 sddc_on_message_lib ,里面调用的 cJSON_Parse 函数会在次级函数中申请内存给root,需要手动释放一下。
(1)使用root = cJSON_Parse(text); //将文本转成json格式,次函数里面申请了一块内存给root
所以在最后要释放rootcJSON_Delete(root ); //释放cJSON_Parse()分配出来的内存空间
(2)使用str =
cJSON_Print(root);//次函数将json数据转成字符串,这个函数内申请了一段内存给out,所以使用完out后也要释放(3)使用cJSON *new_json_str =
cJSON_CreateString(str);//将一个字符串转成一个json对象,函数里面也涉及了内存分配,座椅用完以后也要释放cJSON_Delete(new_json_str
需要注意:cJSON_CreateObject创建的指针,需要使用cJSON_Delete删除,cJSON_Print赋值的指针需要free释放。对应不上是没办法真正释放的。
解决方案:
修改后的 sddc_on_message_lib 代码如下:其实就是在每一个出口处加了一个 cJSON_Delete(root); 函数释放内存。
static sddc_bool_t sddc_on_message_lib(sddc_t *sddc, const uint8_t *uid, const char *message, size_t len) { cJSON *root = cJSON_Parse(message); cJSON *Json_method; uint8_t uimethod =DDC_METHOD_VALIDE; Json_method = cJSON_GetObjectItem(root, "method"); if (NULL == Json_method) { cJSON_Delete(root); return SDDC_FALSE; } if (cJSON_IsString(Json_method)) { if (strcmp(Json_method->valuestring,"set") == 0) { uimethod = DDC_METHOD_SET; } else if (strcmp(Json_method->valuestring,"get") == 0) { uimethod = DDC_METHOD_GET; } else { cJSON_Delete(root); return SDDC_FALSE; } } else { cJSON_Delete(root); return SDDC_FALSE; } if (uimethod == DDC_METHOD_VALIDE) { cJSON_Delete(root); return SDDC_FALSE; } if (uimethod == DDC_METHOD_SET) { int i; /* * 数字量、显示量先查询设置,防止开关量是设备的使能 */ for (i=0; i<G_config->num_dev_reg_num; i++) { object_Number_Set(root, G_config->num_dev_reg[i].objname, G_config->num_dev_reg[i].Num_Fun); } for (i=0; i<G_config->dis_dev_num; i++) { object_Display_Set(root, G_config->dis_dev_reg[i].objname, G_config->dis_dev_reg[i].Dis_Fun); } for (i=0; i<G_config->io_dev_reg_num; i++) { object_IO_Set(root, G_config->io_dev_reg[i].objname, G_config->io_dev_reg[i].IO_Fun); } } else if (uimethod == DDC_METHOD_GET) { object_get(sddc, uid, root, G_config->state_get_reg, G_config->state_get_reg_num, 0); } else { cJSON_Delete(root); return SDDC_FALSE; } cJSON_Delete(root); return SDDC_TRUE; }
这篇关于SDDC-SDK 库内存泄露导致ESP32收不到任何报文记录以及修复,附带cjson可能导致内存泄露的情况的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-01Vue.js 是什么-icode9专业技术文章分享
- 2024-11-01Vue3入门教程:从零开始搭建第一个Vue3项目
- 2024-11-01详解vueRouter4基础教程
- 2024-11-01Vuex4课程:初学者的完整入门指南
- 2024-10-31Vue3课程:新手入门到初级掌握
- 2024-10-31Vue3课程:新手入门到初级应用详解
- 2024-10-31VueRouter4课程:新手入门与实战指南
- 2024-10-31Vuex4学习:从入门到初级实战教程
- 2024-10-31Vue3教程:新手入门与基础实战
- 2024-10-31Vue教程:新手快速入门指南