cJSON在STM32單片機上使用遇到解析數據失敗問題

? ? ? ? 我們在單片機上解析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部分…