我们在单片机上解析JSON格式时(比如在用云平台物联网开发时),可以直接使用cJson库来完成自己的操作,而不需要单独实现,具体使用方法可以搜一下。

  • cJson:一个基于 C 语言的 Json 库,它是一个开源项目,github 下载地址:https://github.com/DaveGamble/cJSON
  • cJson库组成:主要的文件有两个,一个 cJSON.c 一个 cJSON.h。使用时,将头文件 include 进去即可

本次记录下在使用时遇到的一个问题:当json的数据多了之后,单片机在解析数据时就会出解析失败。

问题定位:通过调试器去追踪出问题的位置,发现在parse_object函数中出现错误


/* Build an object from the text. */
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
{cJSON *head = NULL; /* linked list head */cJSON *current_item = NULL;if (input_buffer->depth >= CJSON_NESTING_LIMIT){return false; /* to deeply nested */}input_buffer->depth++;if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')){goto fail; /* not an object */}input_buffer->offset++;buffer_skip_whitespace(input_buffer);if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')){goto success; /* empty object */}/* check if we skipped to the end of the buffer */if (cannot_access_at_index(input_buffer, 0)){input_buffer->offset--;goto fail;}/* step back to character in front of the first element */input_buffer->offset--;/* loop through the comma separated array elements */do{/* allocate next item */cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));if (new_item == NULL){goto fail; /* allocation failure */}/* attach next item to list */if (head == NULL){/* start the linked list */current_item = head = new_item;}else{/* add to the end and advance */current_item->next = new_item;new_item->prev = current_item;current_item = new_item;}if (cannot_access_at_index(input_buffer, 1)){goto fail; /* nothing comes after the comma */}/* parse the name of the child */input_buffer->offset++;buffer_skip_whitespace(input_buffer);if (!parse_string(current_item, input_buffer)){goto fail; /* failed to parse name */}buffer_skip_whitespace(input_buffer);/* swap valuestring and string, because we parsed the name */current_item->string = current_item->valuestring;current_item->valuestring = NULL;if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')){goto fail; /* invalid object */}/* parse the value */input_buffer->offset++;buffer_skip_whitespace(input_buffer);if (!parse_value(current_item, input_buffer)){goto fail; /* failed to parse value */}buffer_skip_whitespace(input_buffer);}while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')){goto fail; /* expected end of object */}success:input_buffer->depth--;if (head != NULL) {head->prev = current_item;}item->type = cJSON_Object;item->child = head;input_buffer->offset++;return true;fail:if (head != NULL){cJSON_Delete(head);}return false;
}

具体位置是在申请内存时出现错误

/* allocate next item */
cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
if (new_item == NULL)
{goto fail; /* allocation failure */
}

这个问题就就比较明确了

在 Keil MDK 环境中为 STM32F103C8T6 编程时遇到内存分配函数返回 NULL 的问题,这通常是由于堆(heap)空间不足或内存管理配置不当引起的。

问题原因分析:

  1. 堆空间不足(最常见原因):

    • STM32F103C8T6 仅有 20KB RAM

    • 默认堆大小只有 512 字节(0x200)

    • 动态内存分配超出可用堆空间

以下是解决方案:

增加堆空间大小(最有效方案)

修改启动文件 (startup_stm32f103xb.s):

assembly

; 查找 Heap_Size 定义
Heap_Size      EQU     0x00000200  ; 原始 512 字节; 修改为更大的值 (例如 4KB)
Heap_Size      EQU     0x00001000  ; 4KB (最大不要超过可用RAM)

计算建议值

  • 总 RAM:20KB (0x5000)

  • 推荐堆大小:2-4KB (0x800-0x1000)

  • 保留足够空间给栈(Stack)和静态变量

修改后重新编译调试,问题得到解决。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/93103.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93103.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/93103.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python3基础语法梳理(三)

接上一篇博客 🎮 猜数字小游戏 - Python版 🧠 游戏规则: 系统随机生成一个 1 到 10 的整数玩家输入猜测的数字使用 if 语句判断玩家猜得是否正确提示“猜对了”或“太大/太小了” import randomsecret_number random.randint(1, 10) att…

【docker】将已有mysql脚本导入镜像内使用

准备SQL脚本将SQL脚本(如init.sql)放在宿主机目录下,例如:/path/to/sql-scripts/init.sql启动MySQL容器并挂载脚本使用 -v 参数将SQL脚本挂载到容器的初始化目录:docker run --name mysql-container \-e MYSQL_ROOT_PA…

【机器学习深度学习】LLamaFactory微调效果与vllm部署效果不一致如何解决

目录 前言 一、问题本质 1.1 问题说明 1.2 问题本质示意 二、常见原因 LLaMAFactory对话模板规则定义 模型对话模板定义规则 三、解决方法 提取代码myset.py 创建jinja文件 安装VLLM 运行VLLM 安装运行open webui流程 四、流程梳理 前言 本文主要讲述的主要内容…

Python入门构建网页

用纯 Python 构建 Web 应用 本教程将带你从零开始,构建一个交互式的待办事项清单。 fasthtml 的核心哲学是“回归初心,大道至简”。在当今复杂的前后端分离技术栈中 ,它提供了一条返璞归真的路径,旨在让你能用纯粹的 Python 构建从…

开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。 相关链接: 开源 Arkts …

Go的defer和recover

在 Go 语言中,defer 和 recover 是两个紧密相关的关键字,主要用于错误处理和资源清理。它们通常一起使用,特别是在处理panic(运行时崩溃)时,确保程序不会直接崩溃,而是能够优雅地恢复并继续执行…

Spring Boot 配置文件常用配置属性详解(application.properties / application.yml)

前言 Spring Boot 的一大优势就是通过简单的配置文件即可快速定制应用行为,而无需编写大量 XML 配置或 Java 代码。Spring Boot 使用 application.properties 或 application.yml 作为核心配置文件,支持丰富的配置属性。 本文将详细介绍 Spring Boot 常用…

uni-appDay02

1.首页-通用轮播组件 轮播图组件需要再首页和分类页使用&#xff0c;封装成通用组件 准备组件自动导入组件 <script setup lang"ts"> import XtxSwiper from /components/XtxSwiper.vue import CustomNavbar from ./components/CustomNavbar.vue </scrip…

FastAPI入门:请求体、查询参数和字符串校验、路径参数和数值校验

请求体 FastAPI 使用请求体从客户端&#xff08;例如浏览器&#xff09;向 API 发送数据。请求体是客户端发送给 API 的数据。响应体是 API 发送给客户端的数据。 使用 Pydantic 模型声明请求体&#xff0c;能充分利用它的功能和优点 from fastapi import FastAPI from pydanti…

Docker的docker-compose类比Spring的ApplicationContext

总一句话是&#xff1a;Docker Compose&#xff1a;集中化管理多个容器及其依赖的资源环境&#xff1b;ApplicationContext&#xff1a;集中化管理 多个Bean 及其运行所需的资源和依赖关系。 1. 整体概念 Docker Compose&#xff1a;用于定义和运行多容器 Docker 应用程序&…

Reason-before-Retrieve(CVPR 2025)

研究方向&#xff1a;Image Captioning论文全名&#xff1a;《Reason-before-Retrieve: One-Stage Reflective Chain-of-Thoughts for Training-Free Zero-Shot Composed Image Retrieval》1. 论文介绍组合图像检索&#xff08;CIR&#xff09;旨在检索与参考图像密切相似的目标…

Idefics2:构建视觉-语言模型时,什么是重要的

温馨提示&#xff1a; 本篇文章已同步至"AI专题精讲" Idefics2&#xff1a;构建视觉-语言模型时&#xff0c;什么是重要的 摘要 随着large language models和vision transformers的进步&#xff0c;视觉-语言模型&#xff08;VLMs&#xff09;受到了越来越多的关注…

再谈fpga开发(fpga调试方法)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】我们之前在学校学习c、c的时候&#xff0c;其实学校漏掉了很重要的一个教学环节&#xff0c;那就是调试、测试。很多时候我们代码写出来了&#xff…

C语言中的数据结构--栈和队列(1)

前言本届开始我们将对数据结构中栈的内容进行讲解,那么废话不多说,我们正式进入今天的学习栈栈是一种很特殊的线性表&#xff0c;它只能在固定的一端进行插入和删除操作&#xff0c;进行数据的插入和删除的一端叫做栈顶&#xff0c;另外一端叫做栈底&#xff0c;栈中的元素遵守…

字符串是数据结构还是数据类型?

比较纠结的一个问题&#xff0c;以下是在网上查到后总结的&#xff0c;不知道对不对&#xff0c;欢迎讨论。这是个触及计算机科学核心概念的精妙问题&#xff01;字符串既可以被视为一种数据类型&#xff0c;也可以被视为一种数据结构&#xff0c;这取决于你观察的视角和讨论的…

Cline与Cursor深度实战指南:AI编程助手的革命性应用

引言 在AI编程工具快速发展的今天&#xff0c;Cline和Cursor作为两款备受瞩目的AI编程助手&#xff0c;正在重新定义开发者的工作方式。作为一名深度使用这两款工具的开发者&#xff0c;我在过去一年的实践中积累了丰富的经验和独到的见解。本文将从技术角度深入分析Cline和Cur…

根本是什么

根本是什么 根本没有了&#xff0c;枝叶还在么&#xff1f; 没有了内涵&#xff0c;外延还有么&#xff1f; 丢弃了根本&#xff0c;再嗨也是无意义&#xff0c;无根据空虚之乐罢了。 人之所行所言所思所想所念皆欲念、历程感怀&#xff0c;情思。所谓得失过往&#xff0c;时空…

springboot基于Java的人力资源管理系统设计与实现

管理员&#xff1a;登录&#xff0c;个人中心&#xff0c;部门管理&#xff0c;员工管理&#xff0c;培训信息管理&#xff0c;员工奖励管理&#xff0c;员工惩罚管理员工考核管理&#xff0c;调薪信息管理&#xff0c;员工调动管理&#xff0c;员工工资管理员工&#xff1a;注…

金字塔降低采样

文章目录image_scale.hppimage_scale.cppmainimage_scale.hpp #ifndef IMAGE_SCALE_HPP #define IMAGE_SCALE_HPP#include <vector> #include <cstdint> #include <utility> // for std::pair #include <algorithm> #include <string> enum cl…

Filament引擎(四)——光照渲染Froxelizer实现分析

Froxelizer主要是用于filament光照效果的实现&#xff0c;生成光照渲染时所需的必要信息&#xff0c;帮助渲染过程中明确哪些区域受哪些光源所影响&#xff0c;是Filament中保证光照效果渲染效率的核心所在。这部分的源码&#xff0c;可以结合filament官方文档中Light Path部分…