超详细的嵌入式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内核会发生什么?

未完待续…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/319761.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第十二讲 单片机驱动彩色液晶屏 如何打包bin档

单片机驱动TFT彩色液晶屏系列讲座 目录 第一讲 单片机最小系统STM32F103C6T6通过RA8889驱动彩色液晶屏播放视频 第二讲 单片机最小系统STM32F103C6T6控制RA8889驱动彩色液晶屏硬件框架 第三讲 单片机驱动彩色液晶屏 控制RA8889软件:如何初始化 第四讲 单片机驱动彩色液晶屏 控…

Python-- if...else

在 Python 中,if 语句是用来进行条件判断的基本结构。它允许您根据一个或多个条件的真假来执行不同的代码块。Python 的 if 语句的基本语法如下: if condition:# do something elif another_condition:# do something else else:# do something if none…

【Linux】线程池实现

📗线程池实现(单例模式) 1️⃣线程池概念2️⃣线程池代码样例3️⃣部分问题与细节🔸类成员函数参数列表中隐含的this指针🔸单例模式🔸一个失误导致的bug 4️⃣调用线程池完成任务 1️⃣线程池概念 线程池是…

C#,求最长回文字符串的马拉车(Manacher)算法的源代码

一、回文字符串(Palindromic String) 回文字符串(Palindromic String)是指前、后向读起来完全相同的字符串。 回文字符串除了答题似乎没有什么用处 :P 二、求解思路 求解字符串的回文子串的基本思路: 1、遍历每个位…

C# 图解教程 第5版 —— 第25章 反射和特性

文章目录 25.1 元数据和反射25.2 Type 类25.3 获取 Type 对象25.4 什么是特性25.5 应用特性25.6 预定义的保留特性25.6.1 Obsolete 特性25.6.2 Conditional 特性25.6.3 调用者信息特性25.6.4 DebuggerStepThrough 特性25.6.5 其他预定义特性 25.7 关于应用特性的更多内容25.7.1…

springboot怎样设置全局的traceId(包括MQ)

一、Controller打印TraceId 1、拦截所有的controller,输入输出将traceId放入MDC中: package com.perkins.ebicycle.mobile.trace;import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.stream.Collectors;import…

深思熟虑可能性模型介绍与使用

深思熟虑可能性模型介绍与使用 如何联系我 作者:鲁伟林 邮箱:thinking_fioa163.com或vlinyes163.com 版权声明:文章和记录为个人所有,如果转载或个人学习,需注明出处,不得用于商业盈利行为。 背景 20…

操作系统详解(5.1)——信号(Signal)的相关题目

系列文章: 操作系统详解(1)——操作系统的作用 操作系统详解(2)——异常处理(Exception) 操作系统详解(3)——进程、并发和并行 操作系统详解(4)——进程控制(fork, waitpid, sleep, execve) 操作系统详解(5)——信号(Signal) 文章目录 题目第一问第二问第三问 题目…

ES搜索的安装以及常用的增删改查操作(已经写好json文件,可以直接使用)

1.es的下载 https://www.elastic.co/cn/downloads/past-releases 2.elasticsearch安装及配置,遇到9200访问不了以及中文乱码,能访问了却要账户密码等问题 Elasticsearch启动后访问9200失败_http://localhost:9200无返回值-CSDN博客 3.开启es服务&#x…

Qat++,轻量级开源C++ Web框架

目录 一.简介 二.编译Oat 1.环境 2.编译/安装 三.试用 1.创建一个 CMake 项目 2.自定义客户端请求响应 3.将请求Router到服务器 4.用浏览器验证 一.简介 Oat是一个面向C的现代Web框架 官网地址:https://oatpp.io github地址:https://github.co…

Error: L6218E: Undefined symbol 系列错误汇总 (referred from main.o)

传送门 错误1: Undefined symbol(referred from main.o)错误2:Undefined_symbol _use_two_region memory 错误1: Undefined symbol(referred from main.o) Cube_GPIO\Cube_GPIO.axf: Error: L6218E: Undefined symbol LED_GPIO_Init (referr…

15个为你的品牌增加曝光的维基百科推广方法-华媒舍

维基百科是全球最大的免费在线百科全书,拥有庞大的用户群体和高质量的内容。在如今竞争激烈的市场中,利用维基百科推广品牌和增加曝光度已成为许多企业的重要策略。本文将介绍15种方法,帮助你有效地利用维基百科推广品牌,提升曝光…

GPT编程:运行第一个聊天程序

环境搭建 很多机器学习框架和类库都是使用Python编写的,OpenAI提供的很多例子也是Python编写的,所以为了方便学习,我们这个教程也使用Python。 Python环境搭建 Python环境搭建有很多种方法,我们这里需要使用 Python 3.10 的环境…

浅谈对Mybatis的理解

一、Mybatis的概述 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,由谷歌托管,并且改名为MyBatis 。2013年11月迁移到Github。 MyBatis是支持普通SQL查询,存储过程和高级映射的优…

ssm基于Web的课堂管理系统设计与实现论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

数据库(1)

目录 1.什么是数据库 1.1.数据 1.2.数据库 1.3 常见数据库 1.3.1 关系型数据库 1.3.2 非关系型数据库 2.mysql概述 ​编辑 **3.MySQL本地仓库安装 在Linux端操作 4.MySQL网络安装 **方法一:RPM捆绑包 下载安装RPM捆绑包: 在windows端操作&a…

开箱即用的企业级前后端分离【.NET Core6.0 Api + Vue 2.x + RBAC】权限框架-Blog.Core

前言 今天要给大家推荐一个开箱即用的企业级前后端分离【.NET Core6.0 Api Vue 2.x RBAC】权限框架(提高生产效率,快速开发就选它):Blog.Core。 推荐原因 Blog.Core通过详细的文章和视频讲解,将知识点各个击破&…

element表格数据,表头上(下)角标,html字符串渲染

1. 问题描述 在动态渲染的element表格中&#xff0c;表头和表中数据是一个含有html的字符串&#xff0c;需要渲染 2. 效果 3. 代码 const columns ref([{ text: 差值<sub>-3</sub> / 10<sup>-6</sup>℃<sup>-1</sup>, value: aallowEr…

三菱FX系列PLC定长切割控制(线缆裁切)

三菱PLC绝对定位指令DDRVA实现往复运动控制详细介绍请查看下面文章链接&#xff1a; https://rxxw-control.blog.csdn.net/article/details/135570157https://rxxw-control.blog.csdn.net/article/details/135570157这篇博客我们介绍线缆行业的定长切割控制相关算法。 未完待…

Xmind 网页端登录及多端同步

好久没用 Xmind 了&#xff0c;前几天登录网页端突然发现没办法登录了&#xff0c;总是跳转到 Xmind AI 页面。本以为他们不再支持网页端了&#xff0c;后来看提示才知道只是迁移到了新的网址&#xff0c;由原来的 xmind.works 现在改成了的 xmind.ai。又花费好长时间才重新登录…