超详细的嵌入式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 String字符串的常用使用方法

《JavaString字符串的常用使用方法》String是JDK提供的一个类,是引用类型,并不是基本的数据类型,String用于字符串操作,在之前学习c语言的时候,对于一些字符串,会初始化字符数组表... 目录一、什么是String二、如何定义一个String1. 用双引号定义2. 通过构造函数定义三、St

Pydantic中Optional 和Union类型的使用

《Pydantic中Optional和Union类型的使用》本文主要介绍了Pydantic中Optional和Union类型的使用,这两者在处理可选字段和多类型字段时尤为重要,文中通过示例代码介绍的... 目录简介Optional 类型Union 类型Optional 和 Union 的组合总结简介Pyd

Nginx中配置HTTP/2协议的详细指南

《Nginx中配置HTTP/2协议的详细指南》HTTP/2是HTTP协议的下一代版本,旨在提高性能、减少延迟并优化现代网络环境中的通信效率,本文将为大家介绍Nginx配置HTTP/2协议想详细步骤,需... 目录一、HTTP/2 协议概述1.HTTP/22. HTTP/2 的核心特性3. HTTP/2 的优

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo

使用Python自建轻量级的HTTP调试工具

《使用Python自建轻量级的HTTP调试工具》这篇文章主要为大家详细介绍了如何使用Python自建一个轻量级的HTTP调试工具,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录一、为什么需要自建工具二、核心功能设计三、技术选型四、分步实现五、进阶优化技巧六、使用示例七、性能对比八、扩展方向建

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Linux中的计划任务(crontab)使用方式

《Linux中的计划任务(crontab)使用方式》:本文主要介绍Linux中的计划任务(crontab)使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、前言1、linux的起源与发展2、什么是计划任务(crontab)二、crontab基础1、cro