? ? ? ? 我們在單片機上解析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)空間不足或內存管理配置不當引起的。
問題原因分析:
堆空間不足(最常見原因):
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)和靜態變量
修改后重新編譯調試,問題得到解決。