MDK5 #254: type name is not allowed

前言

在MDK工程中使用cJSON來分析json文件,突然發現cJSON用內存太猛了。基本是1KB的json文件,要使用3KB~6KB的內存用量。

內存用量猛的原因如下:

  • 內存管理模塊的最小塊單位額爲32Bytes, 如果申請很多次,會浪費很多內存. e.g. "hello"這個字符串,如果要申請內存,就會佔掉32Bytes. 如果json文件的key_value較多,那就會爲很多的key/value申請內存,那內存用量,就要比實際的json文件size大好多。
    但是內存最小塊太小(e.g. 4Bytes), 那內存管理表就很大, 甚至比要管理的有效內存更大。
  • 分析json文件時,json內容就是一棵樹,如果我自己作,肯定也會用單鏈表來作,每個節點下都掛一堆單鏈表。而且還會有一些額外的管理信息。這些額外的管理信息,也會佔用多餘的內存空間。

開始想掛外部內存芯片,原理圖都畫完了,方案被老大給槍斃了。原因如下:

  • 板子畫出來太醜, 因爲屬於打補丁性質的板子,要保持硬件管腳接口(插件)兼容,又多了2個大片子(cpu管腳由100腳上升到144管腳,新加入的內存芯片爲tsop44), 原始板子的原件密度又大(40mm*60mm), 有50個元器件。先不用佈線,將元器件先擺開,那板子體積至少擴大一倍. 板子重心已經偏了,特別的醜:)
  • 動硬件板子,時間成本高。
  • 他感覺,從軟件上優化,能解決這個問題。不使用cJSON庫,自己用手掰json文件的分隔符號,只載入必須的元素,並進行元素替代(e.g. 有些已知的字符串或參數,用變量ID來代表)那樣就省很多空間。web端用json表示的文件內容,可能是web端html的表內容。那這些表內容,有很多都是下位機用不到的。如果完全載入原始的json文件,確實會佔用很多寶貴的RAM空間。特別是,這些json文件載入後,不能釋放。因爲要用於後續的判斷(不可能每次判斷一個邏輯,都再讀一次json文件,肯定要將json配置文件,載入一次後,就緩存起來,不釋放了).

試驗

第一步要做的是,將有些已知的變量內容,用變量ID來表示。
e.g. “param1” 用1000來代替,"hello"用2000
那麼 {“param1”:“hello”} 就可以用 {1000, 2000}來代替。如果{1000, 2000}放在一個有2個int類型值的結構中,那這個結構,就只佔用8個字節.
其中1000,2000用枚舉值自己定義,這樣維護起來,也很方便,不至於看蒙。

那首先,要先定義一個常量結構體數組, 這樣,結構體數組,就在代碼空間內,不會佔用寶貴的片內RAM了。
但是,定義好數組後,總是編譯不過,報錯爲#254: type name is not allowed

回來做了試驗,定義的常量結構體數據,在vs2017和MDK下都編譯過了。
明天接着優化json文件的載入。

可以在vs2017和MDK5中都編譯通過的“常量結構體數組的初始化代碼”如下

#include <stdio.h>
#include <stdlib.h>

#pragma pack(push, 1)

typedef enum _ENUM_dev_id {
	ENUM_DEV_ID_dev1 = 1,
	ENUM_DEV_ID_dev2
}ENUM_DEV_ID;

typedef struct _tag_Info {
	ENUM_DEV_ID id;
	const char* psz_name;
}TAG_INFO;

#pragma pack(pop)

// 將字符串用一個數字表示
// ok on vs2017, error on MDK5
//const TAG_INFO g_ary_for_id_by_name[] = {
//	TAG_INFO{ENUM_DEV_ID_dev1, "dev1"},
//	TAG_INFO{ENUM_DEV_ID_dev2, "dev2" }
//};

// const char* psz_dev1_name = "dev1";
// #define DEV1_NAME "dev1"
// compile both ok on vs2017 and MDK5
const TAG_INFO g_ary_for_id_by_name[] = {
		{ENUM_DEV_ID_dev1, "dev1"}, // “dev1” 只能是常量字符串,不能是常量指針變量psz_dev1_name,否則報錯 “error:  #28: expression must have a constant value” 所以,這裏最多是一個宏 DEV1_NAME
		{ENUM_DEV_ID_dev2, "dev2" }
	};

int main()
{
	int i = 0;
	int i_ary_size = sizeof(g_ary_for_id_by_name) / sizeof(g_ary_for_id_by_name[0]);

	for (i = 0; i < i_ary_size; i++) {
		printf("struct[%d].id = %d\n", i, g_ary_for_id_by_name[i].id);
		printf("struct[%d].psz_name = %s\n", i, (NULL != g_ary_for_id_by_name[i].psz_name) ? g_ary_for_id_by_name[i].psz_name : "NULL");
	}
			
	return EXIT_SUCCESS;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章