超详细的嵌入式cJSON使用注意事项,持续补充中......

2024-01-14 17:36

本文主要是介绍超详细的嵌入式cJSON使用注意事项,持续补充中......,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、堆内存不足
    • 1.1 问题描述
    • 1.2 解决办法
  • 二、内存泄露
    • 2.1 忘记Delete
    • 2.2 忘记Free
    • 2.3 串口数据接收缺少部分字符导致的内存泄露(自己的问题)
      • 问题分析
    • 2.4 内存泄露在Cortex-M3内核会发生什么?

cJSON开源库地址: cJSON

一、堆内存不足

1.1 问题描述

这是大家遇到最多的问题之一,在Keil5中给STM32F103ZET6默认分配的堆大小是0x200,在数据量比较大的时候容易出现内存溢出错误。如果数据量不大,那么无所谓,但是数据量大了就到出现堆内存爆满。

1.2 解决办法

修改堆大小,找到.s文件,再找到堆大小,将0x200修改为0xf00,这个数根据需求定。

在这里插入图片描述

二、内存泄露

2.1 忘记Delete

在使用cJSON_Parse()函数解析json数据后,我们需要释放掉这个函数所申请的内存,因为设计到json嵌套的问题,所以需要使用cJSON库中的释放函数cJSON_Delete()函数

使用示例

root=cJSON_Parse(data);
if(root != NULL)
{/*对root进行进一步解析*/cJSON_Delete(root);	
}

2.2 忘记Free

在这里插入图片描述

在github主页可以看到这段话:使用cJSON_Print()这个函数打印json数据会申请一块内存,在使用完这个函数后你有义务释放掉这个函数所申请的内存

使用示例


char *json_string = cJSON_Print(item);
if (json_string) 
{printf("%s\n", json_string);free(json_string);//1.5版本以上也可以使用以下函数进行释放//cJSON_free(json_string);}

2.3 串口数据接收缺少部分字符导致的内存泄露(自己的问题)

由于return造成的!惨痛的教训

*有问题的代码

//==================================================================
//函 数 名:pid_parameter_change
//功    能:接收字符串格式化为JSON格式,解析其中pid数据,并修改对应pid结构体
//输入参数:字符串指针,pid结构体指针
//返 回 值:0表示解析成功,1表示解析错误
//==================================================================
uint8_t pid_parameter_change(const char *data,PID *pid)
{cJSON *root=NULL;cJSON *kp=NULL,*ki=NULL,*kd=NULL;float p,i,d;root=cJSON_Parse(data);if(root!=NULL){/* 解析Kp */kp=cJSON_GetObjectItem(root,"kp");if(kp == NULL)  return 1;else            p=cJSON_GetNumberValue(kp);/* 解析Ki */ki=cJSON_GetObjectItem(root,"ki");if(ki == NULL)  return 1;else            i=cJSON_GetNumberValue(ki);/* 解析Kd */kd=cJSON_GetObjectItem(root,"kd");if(kd == NULL)  return 1;else            d=cJSON_GetNumberValue(kd);/* 修改PID参数 */pid->Kp=p;pid->Ki=i;pid->Kd=d;printf("%p\r\n",root);cJSON_Delete(root);root=NULL,kp=NULL,ki=NULL,kd=NULL;return 0;}else{cJSON_Delete(root);root=NULL;return 1;   //root数据JSON格式化失败}
}

*修改后的代码

//==================================================================
//函 数 名:pid_parameter_change
//功    能:接收字符串格式化为JSON格式,解析其中pid数据,并修改对应pid结构体
//输入参数:字符串指针,pid结构体指针
//返 回 值:0表示解析成功,1表示解析错误
//==================================================================
uint8_t pid_parameter_change(const char *data,PID *pid)
{cJSON *root=NULL;cJSON *kp=NULL,*ki=NULL,*kd=NULL;float p,i,d;if(data[0] == '{' && data[UART1_Rx_cnt-3] == '}' ){root=cJSON_Parse(data);if(root){/* 解析Kp */kp=cJSON_GetObjectItem(root,"kp");if(kp == NULL)  {    cJSON_Delete(root);return 1;}else            p=cJSON_GetNumberValue(kp);/* 解析Ki */ki=cJSON_GetObjectItem(root,"ki");if(ki == NULL)  {    cJSON_Delete(root);return 1;}else            i=cJSON_GetNumberValue(ki);/* 解析Kd */kd=cJSON_GetObjectItem(root,"kd");if(kd == NULL)  {    cJSON_Delete(root);return 1;}else            d=cJSON_GetNumberValue(kd);/* 修改PID参数 */pid->Kp=p;pid->Ki=i;pid->Kd=d;/*删除JSON,否则可能会发送内存泄露*/cJSON_Delete(root);root=NULL,kp=NULL,ki=NULL,kd=NULL;  // 释放掉的内存指向NULL,避免产生野指针return 0;}else{/*删除JSON,否则可能会发送内存泄露*/cJSON_Delete(root);root=NULL;return 1;   //root数据JSON格式化失败} }else{return 1;}
}

问题分析

这个问题的根源是由于串口接收到的数据不全导致的!同时也有我代码不严谨的问题。
在有问题的那个代码中,使用cJSON_Parse()成功解析出数据,使得代码进入了if语句中 , if(root)
进入if语句后,再次判断json对象是否有ki这个元素
这个时候出现了问题,由于串口接收缺少了ki中的i这个字符,使得if语句判断结果未false,直接return了。 if(ki == NULL) .
注意,return之前我没有使用cJSON_Delete()删除root,所以出现了内存泄露!
写代码的时候没考虑到cJSON_Parse()成功后,解析不出json对象中的元素的问题!

2.4 内存泄露在Cortex-M3内核会发生什么?

未完待续…

这篇关于超详细的嵌入式cJSON使用注意事项,持续补充中......的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/605964

相关文章

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w

Python UV安装、升级、卸载详细步骤记录

《PythonUV安装、升级、卸载详细步骤记录》:本文主要介绍PythonUV安装、升级、卸载的详细步骤,uv是Astral推出的下一代Python包与项目管理器,主打单一可执行文件、极致性能... 目录安装检查升级设置自动补全卸载UV 命令总结 官方文档详见:https://docs.astral.sh/

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

Python包管理工具核心指令uvx举例详细解析

《Python包管理工具核心指令uvx举例详细解析》:本文主要介绍Python包管理工具核心指令uvx的相关资料,uvx是uv工具链中用于临时运行Python命令行工具的高效执行器,依托Rust实... 目录一、uvx 的定位与核心功能二、uvx 的典型应用场景三、uvx 与传统工具对比四、uvx 的技术实

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF