程序在运行时有时候会需要一个很大的空间去临时存储一些变量,如果一开始就分配一个很大的数组区的话,有可能会造成内存的浪费,有可能很长一段时间根本不需要这么大的内存,这就造成了一种情况,如果不分配这么大的空间,需要的时候内存不够,如果分配了,可能有一些功能就要被摒弃_(┐「ε:)_。
动态内存管理就是在这样的背景下产生的,先说说编译器在编译时的内存分配,编译器在编译时会将内存分为 栈区、堆区、BSS区、全局初始化变量区、代码区。而这些区域只有堆区是可以动态管理的,也就是程序可以去申请调用的内存区域,详细的内存分布以及它们之间的特性请看我的另一篇博客,这里就不展开讲了。
今天我要说的是关于单片机的动态内存管理,其实对于单片机开发者而言,也许一辈子都接触不到动态内存动情况,为什么,内存太小了,本来就几k的空间,做内存管理有意义吗,对于这个话题,我且按下不表,这里只做技术展示,不喷口水战(~ ̄▽ ̄~)。
一步一步跟着我走,包教包会,先说说环境,我使用的是5.21版本的keil,在stm32f103v8t6 和 mb9af314n上实验过这份代码,所以这份代码是适用于Cotex-M3系列芯片的。
例子使用的芯片是stm32vet6
第一步,设置 堆 的大小
Heap_Size EQU 0x00000200
//这里设置了堆的大小为512个字节,在启动文件那里,设置堆的大小不能为0,而且必须为4的倍数,如果设置的不是4的倍数会有警告,而且程序跑不动,警告如下
warning: A1581W: Added 1 bytes of padding at address 0x1
原因是指需要字节对齐,stm32为32位机,剩下的自己琢磨去,不展开讲了。
然后在工程配置中打开微苦库,Target 标签栏下勾选上 USE MicroLIB。
然后包含这两个头文件
#include "stdlib.h"
#include "string.h"
然后还有一些需要用掉的宏定义
#ifndef uint16_t
#define uint16_t unsigned int
#endif
#ifndef uint8_t
#define uint8_t unsigned char
#endif
#ifndef TURE
#define TURE 1
#endif
#ifndef FAULSE
#define FAULSE 0
#endif
#ifndef TAIL
#define TAIL 0xffff
#endif
//定义一个结构体节点
struct node
{
int data; //有效数据
struct node *pNext; //指向下一个节点的指针
};
下面是函数的具体实现,我直接贴代码,然后在一一说明
//创建链表节点
struct node* CreateNode(void)
{
struct node* p = (struct node*)malloc(sizeof(struct node));
if(NULL == p)