最近弄json,发现经常的堆溢出,然后找问题。因为对STM32堆栈问题没有深刻认识,就花时间好好研究下了堆栈并且做了验证
1.栈地址区间确定
首先找到启动文件,我的启动文件在startup_stm32f40xx.s,一般的启动文件也都在startup_stm32fxxxx.s文件里
__initial_sp 这个参数是栈顶地址,因为栈的增长是向下增长,所以这个参数我们可以理解为栈的起始地址,我设置的栈尺寸是0x400,所以栈的地址范围是 __initial_sp ~ (__initial_sp - 0x400),__initial_sp 这个参数是keil编译代码之后计算出来的,有多种方法确定。
2.确定__initial_sp数值
(1)方法:1:编译代码,编译完成之后,在代码所在文件夹里找到一个.map的文件,放入keil
(2)方法2:Debug执行代码,然后查看0x08000000这个地址的数据,前四个字节就是
(3)方法3:直接根据RW-data + ZI-data
因为SRAM的基地址是0x20000000,所以上面的地址应该加上基址,也就跟上面吻合了
2.栈的功能
(1)函数中的局部变量是保存在栈里的,确认方法如下
地址为 0x200007a8 在 0x200007b0 ~ 0x200003B0范围里,所以在栈里。
3.堆相关
(1)网上有网友说,全局变量、静态变量是放在堆里的,这个是错误的。堆的知识点,回头有时间我再研究一下。
(2)函数名是存放在flash中的!
4.总结
(1)函数内部局部变量是放在栈里面的
(2)函数名是存放在flash中的
(3)如果运行freertos时,在任务里调用函数时,此时这个函数中内部的变量是存放在freertos分配的内存中,而不是栈里
(4)堆只有调用malloc时,分配的空间才在堆中
(5)实际使用过程中,函数局部变量占空空间大于栈分配空间时,会自动占用堆空间,而不会导致程序挂掉
(6)栈的起始点是栈顶,从顶部向下增长
(7)堆是从底部向上增长,堆栈是连接在一起的