stm32中内存分配(堆、栈、malloc)

参考1:c语言中内存分配

参考2:http://blog.csdn.net/shine0181/article/details/7305551(里面有对malloc和free的源码分析)

1. stm32基础知识

本文章所谈内容是基于stm32平台。所以也许需要对stm32的存储结构说明一下。如图(图片来自stm32数据手册):

                        图1

图1是stm32整体存储器结构图,这些数字指的是存储器的地址范围,如下面倒数第3个Flash对应的地址是0x08000000~0x0807FFFF,

计算得出这部分空间为:512KByte,这个地址就是用来存储代码的;

可以看到flash所在的块(block 0)还有其他几个区,根据名称可以大概知道各个区的作用,具体用途这里无需多讨论。

另外block 0共有512M其中Reserved即为保留区,即可以使用外部flash扩展这个块的存储空间,只要地址在范围内就可以。

 

下面重点来看一下block 1:

往上一个方框,block 1名称就是SRAM,所以这个区域就是用来放置RAM。而图中的64KBSRAM就是stm32内置的RAM,

即是说不用外部扩展RAM(MCU的基本配置就是得有CPU+RAM+外设)也能运行处理器。

所以通常用一片单片机+晶振+电源就能跑了跑马灯程序,原因就是这里,学过单片机的应该都明白这个的。

可以看到这个块也有512MB,所以这个RAM也可以通过外部扩展至512MB,当然外部扩展的肯定不如内置的好用了。

那么这个RAM是干什么的呢?

有计算机基础的同学应该都知道,它就是运行内存,就和电脑、手机上经常说的几G内存是同一个东西。

它的作用就是把flash(这里只对于stm32来说)里正在运行的代码段(函数、变量等等)放进这个内存里,

然后CPU对这里面的数据进行读写操作,得出你想要的结果。

而我们经常说的堆、栈也是属于这片区域的,这里所说的堆栈和数据结构的堆栈概念不能混为一谈,当然也是类似的。

stm32的堆、栈设置可以在底层驱动文件startup_stm32f10x_hd.s(这个文件要看你所用MCU的型号,这个是大容量的)里设置。

就是改下面两句的值:

Stack_Size EQU 0x00000400 ;栈大小

Heap_Size EQU 0x00000200   ;堆大小

可以看到只能设置堆、栈的大小,不能设置起始地址和终止地址;

通过度娘查到堆、栈的起始地址设置是在.sct文件中的,具体设置方法还需进一步翻阅相关资料,这里不讨论。

用默认配置,则编译器会自动分配地址给堆栈。这个地址当然要在RAM规定的内存范围内。

由图1(stm32存储器映像图)可以知道,堆栈地址在0x20000000~0x2000FFFF范围内,通过查找.map文件关键字:__initial_sp

可以找到栈地址。堆地址暂时不知道怎么搜索到,也许是因为动态分布和不连续性的原因,编译器无法给出初始地址。

stm32的存储器就先介绍到这里,根据图1再往上就是外设的地址了,图中标识的很明确,也就不细说了。

2. 堆、栈、malloc的使用

到这里stm32的堆栈的位置已经很明确了。所以可以着重来谈谈几个关键概念的使用了。

2.1 堆的使用

1、堆的使用是要结合malloc函数,即使用一次malloc所得到的内存空间既是属于堆的空间。

2、堆的增长方向是向上,所以malloc申请的地址也是越来越大的,前提是连续申请且在最后一次申请后再释放内存(free)。

则第一次申请的地址永远小于后面申请的地址。

3、堆是不连续的,由于RAM中还存在局部变量,代码段和栈等等,所以动态分配的内存是取暂时空闲的内存,

而不是预先划出一块区域,这就是动态分配内存的好处。

4、使用堆的坏处,由于使用malloc申请内存时,不单只申请了所需的大小空间,还要额外暂用管理这部分空间的内存,而释放时又只释放申请的内存,

所以使用堆会引入内存碎片。当然如果不是在短时间内频繁的使用malloc申请和free释放内存,那么操作系统就有足够的时间来回收碎片空间。

2.2 栈的使用

1、由编译器分配,目的是将RAM划分处一块区域供程序运行时的局部变量参数等使用;

2、栈是一块连续的内存空间,由上往下增长,即使用栈时地址是会越来越小的,如先声明的局部变量比后声明的地址要高;

3、栈是由程序(操作系统)自动分配,不会有内存碎片的问题;

4、栈的坏处:栈是固定且连续的一个大小,如果使用局部变量等超出了栈的大小则会造成内存溢出,

而编译器通常是发现不了的,只有当程序运行到那个函数时才会发生的。这就会引入很难查找的bug。

另外如如果使用malloc申请的内存不规范使用,当释放内存后,没将指针地址清空,仍指向那个地址刚好是栈的地址,则会造成越界访问。

2.3 malloc和free的使用

1、这两个函数是配对使用的,如果申请了一个内存,而没有使用free释放,反复的操作后就很快会发生内存溢出,造成难以查找的问题。

所以申请了要释放很重要。

2、malloc使用格式:

char * Onebyte;//声明一个char指针
Onebyte = (char*)malloc(sizeof(Onebyte));//向堆中申请一个字节内存
//下面两句效果一样,若在函数里
char Onearr[10];//向栈中申请10个字节
char *Onearr = (char*)malloc(10);//向堆中申请10个字节

3、free的使用:

//对于上面malloc的使用
free(Onebyte);
free(Onearr);

3. 总结

学会内存管理可以解决一些非常棘手的问题,如:内存溢出,内存越界访问等等。

内存溢出编译器不能发现,引入的问题通常只能在运行代码时才能出现,且是影响到其他代码的运行。

在一个多任务嵌入式系统中如果出现该问题,则会变现的很奇怪,会影响到各个任务的运行。

所以才会说懂内存管理是很重要的。

 

  • 13
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值