赞
踩
一般在编程时,我们都不需要考虑堆栈空间的大小,因为在启动文件中都对堆栈空间的大小进行了设置。
如以下截取stm32启动文件部分汇编代码,Stack栈的大小为:0x400(1024Byte),Heap堆的大小为:0x200(512Byte)。
; 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 0x400 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 0x200 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit
这也是为什么一个空的的工程编译后,RAM的空间也占用了1.6K的原因,因为堆栈的空间均分配在RAM中。可以在map文件中查看具体占用大小
如下图所示,可以在打开启动文件页面后,点击Configuration Wizard,可在Option的设置框中设置堆栈空间的大小
若局部变量较多、定义的数据长度,加一起的空间大于**栈(Stack)**的空间,则会导致栈溢出,程序运行结果与预期的不符或程序跑飞。这时需要手动的调整栈的大小,来复合我们的需求
若使用了malloc动态分配内存空间时,大于设置的**堆(Heap)**的空间。会导致溢出,需要调整堆的大小
一般堆是由低地址往上(高地址)增长,栈是由高地址向下(低地址)增长。都是连续的,C语言不提供内存保护机制类似的功能,如果一直堆一直增长,栈一直申请,然后就会导致栈溢出,程序崩溃
一般堆栈的起始地址是不固定的,是根据用户定义的变量的数目和大小决定的,是编译器自动分配的,内存首先存放/开辟全局变量区域,然后开辟栈区最后开辟堆区
栈首地址=全局区域大小+栈大小(Stack_Size)
其实内存四区和内存五区所指的东西是一样的,对于内存四区而言,其只是把全局区(静态区)和常量区合并为一个数据区而已,其实内容都是完全一样的
栈区、堆区、数据区(全局区(静态区)、常量区)、代码区
栈区、堆区、全局区(静态区)、常量区、代码区
全局变量、静态变量(全局or局部)
int a = 0; //全局初始化区 char *p1; //全局未初始化区 int add(int a; int b) { int sum = 0; //栈 static temp; //全局(静态)未始化区 sum = a+b; return sum; } int main() { int b; //栈 char s[] = "abc"; //栈 char *p2; //栈 char *p3 = "123456"; //123456\0在常量区,p3在栈上 static int c = 0; //全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区 strcpy(p1, "123456"); //123456\0放在常量区, 编译器可能会将它与p3所指向的"123456"优化成一块 return 0; }
参考连接
https://www.e-learn.cn/topic/3842454
https://blog.csdn.net/u011764302/article/details/103368274
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。