ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

SDDC-SDK 库内存泄露导致ESP32收不到任何报文记录以及修复,附带cjson可能导致内存泄露的情况

2022-04-13 17:00:50  阅读:179  来源: 互联网

标签:cJSON 泄露 ESP32 SDDC 内存 root reg sddc Delete


项目场景:

之前为了方便 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
所以在最后要释放root

cJSON_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;
}

标签:cJSON,泄露,ESP32,SDDC,内存,root,reg,sddc,Delete
来源: https://www.cnblogs.com/inspiration-desktop/p/16141045.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有