STM32的堆与栈与编译信息查看
STM32的堆与栈与编译信息查看
因为一个项目中使用malloc函数动态分配内存400多个字节,返回为0,分配失败。查找失败原因,为堆空间不足分配导致。查看堆和栈分别设置了2K,按正常情况看应能满足分配空间,原因可能因为栈分配空间不够,导致到堆的内存空间致使,堆的内存空间过小。下面就说一下STM32的RAM区的分配,堆和栈的信息和编译信息查看。
以下引用网上资料 理解堆和栈的区别和KEIL打印信息的理解
(1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似
于数据结构中的栈。
(2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。分配
方式类似于数据结构中的链表。
(3)全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态
变量在一块区域(数据段),未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(BBS段)。程序结束后由系
统自动释放。BBS-Block Started by Symbol(由符号开始的块)
(4)文字常量区:常量字符串就是存放在这里的。
(5)程序代码区(FLASH):存放函数体的二进制代码。(文本段)
例如:
int a=0; //全局初始化区
char *p1; //全局未初始化区
main()
{
int b; //栈
char s[]="abc"; //栈
char *p3= "1234567"; //在文字常量区Flash
static int c =0 ; //静态初始化区
p1= (char *)malloc(10); //堆区
strcpy(p1,"123456"); //"123456"放在常量区
}
所以堆和栈的区别:
stack的空间由操作系统自动分配/释放,heap上的空间手动分配/释放。
stack的空间有限,heap是很大的自由存储区。
程序在编译期和函数分配内存都是在栈上进行,且程序运行中函数调用时参数的传递也是在栈上进行。
在keil的Build时会有打印(在IAR里没有看到有打印信息)
Program Size:Code=XX RO-data=XX RW-data=XX ZI-data=XX
其中:
Code: 存储到flash[Rom]中的程序代码。(文本段)
RO-data:(Read Only)只读常量的大小,如const型。(数据段)
RW-data:(Read Write) 初始化了可读写变量的大小。即已初始化为非零的全局变量。 (数据段)
ZI-data:(Zero Initialize) 没有初始化或初始化为0的可读写的变量的大小(不会被算做代码里,因为不会被初始化)。 (BBS段)
ROM(Flash) size = Code+RO-data+RW-data;
RAM size = RW-data+ZI-data
如果一个变量被初始化为0,则该变量的处理方法与未初始化变量一样放在ZI区法域。即ARM C程序中,所有的示初始化变量都会被自动初始化为0。
总结:
1、C中的指令以及常量被编译后是RO类型数据
2、C中的未被始化或初始化为0的变量编译后是ZI类型数据。
3、C中已被初始化成非0的值的变量编译后是RW类型数据
4、以上变量指全局变量,局部变量是以上程序中在栈中分配。
ROM指:NAND Flash,Nor Flash
RAM指:PSRAM,SDRAM,DDRAM
Keil IDE的编译信息在工程文件夹的xx.map文件中,STM32的RAM分区从0x0200 0000开始,静态区、堆、栈。
所有的全局变量,包括静态变量之类的,全部存储在静态存储区。然后是堆区(如没用到malloc,则没有该区),之后是栈区,栈在程序中存储局部变量。
; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x00000200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
这里定义了堆栈各自大小,堆:512bytes 栈1k;
所以栈区大小有限制,我们在局部变量中不要定义大数组否则容易溢出。
查看xx.map文件
Removing Unused input sections from the image.就是将库中没有用到的函数从可执行映像中删除掉,减小程序的体积。第一行
Removing startup_stm32f10x_md.o(HEAP), (512 bytes).
意思是因为没有使用malloc动态分配内存,所以没有分配堆。
==============================================================================
Image Symbol Table
Local Symbols 符号表里的局部符号。
Symbol Name Value Ov Type Size Object(Section)
最后一项
STACK 0x2000560 Section 1024 startup_stm32f10x_md.o(STACK)
Global Symbols 符号表里的全局符号
Symbol Name Value Ov Type Size Object(Section)
最后一项
__initial_sp 0x2000960 Data 0 startup_stm32f10x_md.o(STACK)
STACK是栈底,__initial_sp 栈顶地址,此地址被存在Flash0x0800 0000中,占用四个字节。
所以栈大小 为 0x400 即1024个字节。
再加入malloc看一下:
HEAP 0x20000568 Section 512 startup_stm32f10x_md.o(HEAP)
STACK 0x20000768 Section 1024 startup_stm32f10x_md.o(STACK)
__heap_base 0x20000568 Data 0 startup_stm32f10x_md.o(HEAP)
__heap_limit 0x20000768 Data 0 startup_stm32f10x_md.o(HEAP)
__initial_sp 0x20000b68 Data 0 startup_stm32f10x_md.o(STACK)
可见分配了堆,大小为512 bytes在栈的下面,这里也可以看出, 堆向上增长,栈向下增长
如果栈分配的空间不足,将会占用堆的空间,malloc时,可能因为堆空间不足,导致不能分配内存。
要想分配堆空间和栈空间的大小可以设置启动文件的和Heap_Size和Stack_Size的值,随着堆分配和栈分配空间加大,此时编译后看到ZI-data将相应变大,但这个并不是真正的变大,只是分配了较大的空间,可能并没有使用。
网上还有把栈顶直接分配到RAM的最高处,这样不管如何分配栈空间,基本不会导致内存溢出。
另外此文中的.map里的例子,也是直接引用网上的内容!
将我的与非博客搬到博客园!
-----------------------------
STM32的堆与栈与编译信息查看的更多相关文章
- stm32 堆和栈(stm32 Heap & Stack)【worldsing笔记】
关于堆和栈已经是程序员的一个月经话题,大部分有是基于os层来聊的. 那么,在赤裸裸的单片机下的堆和栈是什么样的分布呢?以下是网摘: 刚接手STM32时,你只编写一个 int main() ...
- stm32 堆和栈(stm32 Heap & Stack)
关于堆和栈已经是程序员的一个月经话题,大部分有是基于os层来聊的. 那么,在赤裸裸的单片机下的堆和栈是什么样的分布呢?以下是网摘: 刚接手STM32时,你只编写一个 int main() { whil ...
- 从“关于Java堆与栈的思考”一帖看错误信息的传播
我对转贴的信息一直有敌意,原因如下:首先,除了制造更多的信息垃圾,转贴不会带来新的价值,想收藏的话一个链接足矣:其次,将错误信息以讹传讹,混淆视听.不妨选一个典型的例子说明一二. 相信<关于Ja ...
- JVM学习(2)——技术文章里常说的堆,栈,堆栈到底是什么,从os的角度总结
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 堆栈是栈 JVM栈和本地方法栈划分 Java中的堆,栈和c/c++中的堆,栈 数据结构层面的堆,栈 os层面 ...
- 译文---C#堆VS栈(Part One)
前言 本文主要是讲解C#语言在内存中堆.栈的使用情况,使读者能更好的理解值类型.引用类型以及线程栈.托管堆. 首先感谢原文作者:Matthew Cochran 为我们带来了一篇非常好的文章,并配以大量 ...
- 理解java虚拟机内存分配堆,栈和方法区
栈:存放局部变量 堆:存放new出来的对象 方法区:存放类的信息,static变量,常量池(字符串常量) 在堆中,可以说是堆的一部分 创建了一个student类,定义了name属性, id静态变量 ...
- Java堆、栈和常量池以及相关String的详细讲解(经典中的经典) (转)
原文链接 : http://www.cnblogs.com/xiohao/p/4296088.html 一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的 ...
- Java堆、栈和常量池以及相关String的详细讲解
一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...
- Linux程序存储结构与进程结构堆和栈的区别【转】
转自:http://www.hongkevip.com/caozuoxitong/Unix_Linux/24581.html 红客VIP(http://www.hongkevip.com):Linux ...
随机推荐
- OC和Swift进行互相调用
swift调用oc的方法: 1.桥接文件,一般是swift工程,在创建一个oc文件时,系统自动添加(不用改名,直接默认即可) 2.将需要引用的oc文件 .h头文件 添加到桥接类中. 如下: 然后在sw ...
- Leetcode题目53.最大子序和(动态规划-简单)
题目描述: 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4],输出: 6解释: 连 ...
- Ubuntu桌面版与服务器版的区别(转)
Ubuntu桌面版vs服务器版 提到安装Linux,Ubuntu可谓是最受欢迎的.为了满足每个人的需求,出现了不少版本或风格的Ubuntu:其中两项便是桌面版与服务器版.只要发布版本号一致,这两者从核 ...
- webpack4 打包 library 遇到的坑
output: { publicPath: '/', path: path.join(__dirname, 'lib'), filename: 'chart.js', library: 'tchart ...
- Linux dd烧写系统
虽然用dd指令烧写系统很简单,但是久而久之忘得也太快了,赶紧整理一下. .img 系统镜像 .iso U盘启动引导文件 1. 先来查看本机磁盘情况,打开Linux终端界面(快捷键Ctrl + Alt ...
- LeetCode 复原IP地址(探索字节跳动)
题目描述 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 示例: 输入: "25525511135" 输出: ["255.255.11.135&qu ...
- [面试] Java高级软件工程师面试考纲(转)
如果要应聘高级开发工程师职务,仅仅懂得Java的基础知识是远远不够的,还必须懂得常用数据结构.算法.网络.操作系统等知识.因此本文不会讲解具体的技术,笔者综合自己应聘各大公司的经历,整理了一份大公司对 ...
- JS选择器querySelector和~All,三个原生选择器
定义: querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素. 注意: querySelector() 方法仅仅返回匹配指定选择器的第一个元素.如果你需要返回所有的元素,请 ...
- solr 初接触
solr教程,值得刚接触搜索开发人员一看 http://blog.csdn.net/awj3584/article/details/16963525
- MySQL安装Write configuration file 提示:configuration file template my.ini Error code-1
在安装MySQL的时候, 在最后安装时,最后一步出现Write configuration file没成功勾选,并提示:configuration file template D:\mysql\my- ...