关键词:
STM32的堆与栈与编译信息查看
因为一个项目中使用malloc函数动态分配内存400多个字节,返回为0,分配失败。查找失败原因,为堆空间不足分配导致。查看堆和栈分别设置了2K,按正常情况看应能满足分配空间,原因可能因为栈分配空间不够,导致到堆的内存空间致使,堆的内存空间过小。下面就说一下STM32的RAM区的分配,堆和栈的信息和编译信息查看。
以下引用网上资料 理解堆和栈的区别和KEIL打印信息的理解
(1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似
于数据结构中的栈。
(2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。分配
方式类似于数据结构中的链表。
(3)全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态
变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系
统自动释放。
(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的可读写的变量的大小(不会被算做代码里,因为不会被初始化)。
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里的例子,也是直接引用网上的内容!
将我的与非博客搬到博客园!
-----------------------------
java堆与栈
栈是运行时的单位,而堆是存储的单元。栈解决程序的运行问题,即程序如何执行,或者说如何处理数据,堆解决的是数据存储的问题,即数据怎么放,放在哪儿。 在java中一个线程就会相应有一个线程栈与之对应,这... 查看详情
java中的堆与栈
对于初学者来说,java成员方法中的参数传递的究竟是什么可能有些疑惑,如果理解java在创建变量堆和栈的使用,一切就能清楚明白了。 java中堆和栈都是用来存放数据的地方。 1、栈的特点是存取速度快,数据可共... 查看详情
java堆与栈
Java的堆是一个位于随机访问存储器(RAM)的运行时数据区。通常使用new操作符在堆中创建对象,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译... 查看详情
程序的段堆与栈
1.程序就是编译出来的镜像,处于执行状态的程序叫进程.一个程序可以执行多次,每次执行会产生一个进程.2.程序镜像里有分成很多个段: 段其实就是在程序镜像文件里从一个位置到另一个位置范围里存放某种数据,便于系统... 查看详情
堆与栈
一、数据结构中的堆与栈 在数据结构中,堆与栈为两种常见数据结构,数据结构共分为三大类:表、树、图,堆为树类数据结构,栈为表类数据结构。堆: 堆是一种经过排序的树形数据结构。每一个结点都有一个值,像... 查看详情
堆与栈
静态分配是指在编译阶段就能确定大小,由编译器进行分配,堆不可以进行静态分配,堆的申请都是在执行过程中进行的。堆和栈的大小都可以设置,栈一般只有几KB。堆在动态分配时,要申请连续的内存空间,释放后会产生碎... 查看详情
数据结构堆、栈与程序内存的堆、栈怎么区别
最近对数据结构的堆、栈与程序内存的堆、栈分不太清。请哪位牛人帮忙解惑解惑一下。主要是想看数据结构的堆与程序内存的堆比,数据结构的栈与程序内存的栈比,的区别。这是两套东西的根本就不要搞在一起当然程序运行... 查看详情
c++堆与栈的简单认识
...申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码... 查看详情
堆与栈区别
...用寄存器是不够的,因此这个需要就使用了内存2内存的堆与栈内存:栈,堆栈堆2.1栈的理解对于栈,特点是先进后出;先进的在底部,后放的在顶部;如桶里放的东西,先放进去的内容最后才能拿... 查看详情
堆与栈(未完)
1,堆:堆是共享的,用于储存对象,内存中最大的存储空间,在虚拟机启动的时候就启动起来了 在对象使用结束后,GC会自动回收内存 在堆满后,会溢出,程序就会崩溃 内存不连续,可能产生碎片,需... 查看详情
堆与栈的区别
数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,而不是对象... 查看详情
堆与栈区别(代码片段)
...用寄存器是不够的,因此这个需要就使用了内存2内存的堆与栈内存:栈,堆栈堆2.1栈的理解对于栈,特点是先进后出;先进的在底部,后放的在顶部;如桶里放的东西,先放进去的内容最后才能拿... 查看详情
堆与栈的比较
1、申请方式(1)栈(stack):由系统自动分配。(2)堆(heap):需程序员自己申请(C:调用malloc,realloc,calloc申请free来释放),并指明大小,并由程序员进行释放。容易产生内存泄漏。2、申请大小的限制(1)栈:在windows下... 查看详情
“java”内存区域-“堆与栈”
本文是我阅读周志明老师《深入理解Java虚拟机-JVM高级特性与最佳实战》章节2.2的学习笔记。更多内容,请参考原书。 Java虚拟机在执行Java程序时会将其所管理的内存划分为若干个不同的数据区域,这些区域有各自的用... 查看详情
bss段数据段代码段堆与栈
BSS段:BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。 BSS是英文BlockStartedbySymbol的简称。BSS段属于静态内存分配。数据段:数据段(datasegment)通常是指用来存放程序中已初始化的全局变... 查看详情
heapspray:堆与栈的协同攻击
1:应用场景在针对浏览器的攻击中,常常会结合使用堆和栈协同利用漏洞。(1)当浏览器或其使用的ActiveX控件中存在溢出漏洞时,攻击者就可以生成一个特殊的HTML文件来触发这个漏洞。(2)不管是堆溢出还是栈溢出,漏洞触发... 查看详情
虚拟内存布局内存的分工堆与栈
进程的虚拟内存空间分为两个部分。低2GB(或3GB_)由应用程序使用。高2GB(或1GB)由系统内核程序使用。系统内核的内存空间中包含驱动程序,系统内核可运行程序、用于内存管理的数据结构(页文件夹、页表等),用于进程管理... 查看详情
数据结构初探栈与栈的应用(代码片段)
(一)在描述栈(stack)之前,我们先了解一下数据结构基础概念:1、数据(data)是对客观事物的符号表示,数据元素(dataelement)是数据的基本单位,一个数据元素可由若干个数据项(dataitem)组成,数据项为数据的不可分割... 查看详情