超详细的嵌入式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

相关文章

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

MyBatis ParameterHandler的具体使用

《MyBatisParameterHandler的具体使用》本文主要介绍了MyBatisParameterHandler的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、概述二、源码1 关键属性2.setParameters3.TypeHandler1.TypeHa

Spring 中的切面与事务结合使用完整示例

《Spring中的切面与事务结合使用完整示例》本文给大家介绍Spring中的切面与事务结合使用完整示例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录 一、前置知识:Spring AOP 与 事务的关系 事务本质上就是一个“切面”二、核心组件三、完

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

使用Python实现Word文档的自动化对比方案

《使用Python实现Word文档的自动化对比方案》我们经常需要比较两个Word文档的版本差异,无论是合同修订、论文修改还是代码文档更新,人工比对不仅效率低下,还容易遗漏关键改动,下面通过一个实际案例... 目录引言一、使用python-docx库解析文档结构二、使用difflib进行差异比对三、高级对比方

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca