优化内存_内存泄漏——C
内存分配未成功,却使用了它。
编程新手常犯这种错误,因为他们没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行
检查。如果是用malloc或new来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。
通过以下四种方法可以优化 ESP8266 应用的内存使用,减少应用的内存占用空间。
1. 将字符串放到 Flash 中:
(1) 有些字符串可以放在 Flash 中,特别是长字符串,例如 HTML 请求和响应模板。
比如,一个字符串原来是用 define 定义的:
#define test_string "hello world”
现在可以定义成如下:
static const char test_string[] ICACHE_RODATA_ATTR = "hello world";
(2) 当用 ICACHE_RODATA_ATTR 定义字符串常量时,需要对数据内容进行四字节对齐读取。由于 Flash 中的数据需要四字节对其读取,所以定义一个宏获取对齐后的字符串长度:
#define GET_ALIGN_STRING_LEN(str) ((strlen(str) + 3) & ~3)
使用字符串时,动态分配一个新的数组对象,读写 Flash 中的数据。然后用 os_memcpy API 来复制数据内容:
unsigned int str_len = GET_ALIGN_STRING_LEN(test_string);
char *tmp_string = (char *)os_malloc(str_len);
os_memcpy(tmp_string, test_string, str_len);
(3) 在用户的应用代码里使用 tmp_string 进行操作,而不使用 test_string。此方法除了减少应用的 RAM 占用空间,也能解决由于对 Flash 中的数据进行非对齐读取时,在应用中引起的 exception。
…….
(4) 当用户代码中,无需再使用通过以上方法读取的数据,需要释放之前分配的内存空间
os_free(tmp_string);
注意:如果不释放之前分配的内存空间,重复分配内存将会减少核心功能所需的内存,导致 API 出现功能异常或失败。
2. 把 const 数据放到 Flash:
(1) uint32 类型的数组可以直接放到 Flash,比如:
const uint32 array[4] ICACHE_RODATA_ATTR = {0x11111111, 0x22222222, 0x33333333, 0x44444444};
可以直接使用 array[0]。
(2) 对于 uint8 和 uint16 类型的数组,要注意读取数据的时候要四字节对齐,
比如:
const uint8 array[7] ICACHE_RODATA_ATTR = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
(3) 如果需要按字节读取 char 数组当中的元素,可从软件上进行处理,先按四字节读取,然后再按偏移取当中的一个字节。如果直接读取 array[0],会导致 crash。
(4) 对于数据结构,通常做法是分配比用户需要读取的结构更大的内存,从 Flash 四字节读取数据到内存。如同方法 1,在代码中依然使用对象指针。修改代码操作内存中的数据结构,而不是读取数组。
3. 将调试字符串放到 Flash 中:
现在默认的 printf 打印的字符串都还是放在 RAM 区,占用部分内存。如果用户无需频繁打印日志文件,或者调试字符串太长,可以使用优化的 os_printf 把打印的字符串放到 Flash 而不是 RAM 中。
4. 避免使用全局数组变量:
全局数组变量会在应用的整个生存期中占用不必要的内存。为减少全局数组变量的使用,乐鑫提供了动态内存分配 API。在基于事件的编程中,请使用 os_malloc 和 os_free 来动态分配所需的内存空间。但注意,我们不建议过于频繁地分配和释放大小不等的内存空间。
最新文章
- 准循环LDPC码用于公钥密码时的奇偶校验矩阵
- OPRNGL总结(一)OPENGL的理论原理
- BZOJ 1015 题解
- linux读写ntfs
- [Java] HashMap的用法
- Tachyon Cluster: 基于Zookeeper的Master High Availability(HA)高可用配置实现
- 【JavaScript你需要知道的基础知识~】
- Windows平台下搭建MySQL数据库
- 初识php soap 学习过程中的摘抄,便于后期翻阅
- C#图解教程 第十一章 枚举
- 如何更好的编写async函数
- photoKit使用笔记
- Ubuntu 14.04 下安装 OpenCV
- Bukkit编程之动态向yml文件中添加属性
- MVC教程七:扩展HtmlHelper方法
- (转)MySQL 插入数据时,中文乱码问题的解决
- mybatis第二天——动态SQL与关联查询
- [Oracle整理]ORA-12705(字符集问题)
- SCWS 中文分词
- 【C#】枚举和字符串以及数字之间的互相转换
热门文章
- Insomni'hack teaser 2019 - Pwn - 1118daysober
- C++ GUI Qt4学习笔记08
- 子类重用父类的功能super
- 移动web开发之像素和DPR详解
- 对postcss以及less和sass的研究
- 状态管理工具对比vuex、redux、flux
- C++STL手写版
- 洛谷P3373 【模板】线段树 2 &;&; P2023 [AHOI2009]维护序列——题解
- clientX、pageX、offsetX、screenX的区别
- 对象转json串.