赞
踩
关于程序的内存分配
栈区、堆区、全局区静态区存储在SRAM中,文字常量区和程序代码区存放在Flash中。通过Rebuild可以看出整个内存分配。
Code:存储代码
RO-data:存储const常量和指令
RW-data:存储初始化值不为0的全局变量、静态变量
ZI-data:存储初始化值为0的全局变量、静态变量
所以Flash = Code+RO-data+RW-data,SRAM = RW-data+ZI-data
在.map文件中也可以看见
47648 = 0xBA20,所以SP指针的栈顶地址是0x2000BA20。
打开.map文件可以查看程序的内存分配
0x20000000是sram开始的地址,可以看到各段的分布。
STACK:栈区
HEAP:堆区
.data:初始化的全局变量、静态变量
.bss:未初始化或者初始化为0的全局变量、静态变量
0x08000000是flash开始的地址,可以看到各段的分布。
.constdata:文字常量区
Code:函数代码
在Options for Target页面中可以设置Flash和SRAM大小:
我们只在启动文件中设置了栈区、堆区的大小,并未设置全局区的大小,如果有定义全局变量,则sram先给全局区分配内存,再给栈区分配内存(最后分配)。
从下图中可以看出,最后从0x2000aa20开始分配了0x1000大小的STACK栈空间。mallco.c中定义了一个大小40K的全局数组(未初始化),数组在内存的地址从0x20000020开始,大小为0xA000,再加上其他的未初始化全局数组就达到了0x2000aa20。
目前两种内存获取方式:
同庞大的全局变量数组来圈住一块内存,然后将这个内存拿来进行内存管理和分配。
把编译器未使用的RAM部分用于做内存分配,也就是除掉RW-data+ZI-data+编译器堆+编译器栈 后剩余的RAM内存中的一部分或者全部进行内存管理和分配。这种情况下需要知道内存剩下部分的首地址和内存的尾地址,然后要用多少内存,就从首地址开始挖,做一个链表,把内存获取和释放相关信息链接起来,就能及时的对内存进行管理了。
生长方向:
堆:向上生长
栈:向下生长
数组:向上生长
定义在栈中的数组仍然是向上生长的,局部变量是从高地址开始往低地址存。
注意:局部变量用数组过大会导致栈溢出。
void test()
{
u32 buff[] = {0x01234567,0x89abcdef};
u32 *p = buff;
printf("0x%x", *(u32*)((u8*)p+1));
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。