MDK5 #254: type name is not allowed
发布日期:2021-06-30 22:01:51
浏览次数:2
分类:技术文章
本文共 2323 字,大约阅读时间需要 7 分钟。
前言
在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#include #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 MDK5const 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;}
转载地址:https://lostspeed.blog.csdn.net/article/details/103500483 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月16日 20时31分47秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
进程和多进程实现多任务
2019-05-01
python模块os.getpid 和os.getppid在多进程中的应用
2019-05-01
python 实现多线程UDP聊天器
2019-05-01
多进程之间共享全局变量 python实现
2019-05-01
进程方法 run和start的区别
2019-05-01
python 多进程之进程池的操作
2019-05-01
进程池之间通信 python 实现
2019-05-01
基于进程池实现文件拷贝
2019-05-01
作最好的自己
2019-05-01
python 计算占用内存空间
2019-05-01
垃圾回收 python实现
2019-05-01
列表的加法 a=a+b和 a+=b有什么区别
2019-05-01
python 面向对象 继承之 supper 函数
2019-05-01
生成器公式实现生成器与yield 实现生成器 python实现
2019-05-01
在大量创建类时减少内存消耗 python实现
2019-05-01
python学习之tkinter 从一个错误说起
2019-05-01
mysql学习之子查询
2019-05-01
未来1年的目标
2019-05-01
shell脚本 获取命令执行反馈和在命令执行后一段时间杀死进程
2019-05-01
mysql学习之where 和having
2019-05-01