
![]() 以下引用网上资料 理解堆和栈的区别 (1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似 - \9 T2 n5 H4 R( _8 j 于数据结构中的栈。: Q1 a- v8 |% m5 `/ `' z! i ; K$ m5 \( k5 y* D, e5 f9 O (2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。分配! M, k' @- g4 F$ F7 b# _ 7 f2 ^2 A! ^9 H6 s/ b: ~ 方式类似于数据结构中的链表。0 Y% S7 s2 d. M) R1 O g 6 i( Q+ j7 O' @% `5 P (3)全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态. ]6 V( r y% \# f 变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系! L/ D# h$ @ X3 b 统自动释放。' D4 ]5 U/ O. d9 M+ Z9 w( V' `9 y 3 ^% w9 d2 B3 O8 }' t9 r- u# u k: q (4)文字常量区:常量字符串就是存放在这里的。 & |/ h9 O& Q: k (5)程序代码区:存放函数体的二进制代码。- M0 D# r& U6 R# K& t, R 例如:5 r2 U+ h _( ~" F E" X 7 t. R- J- Y8 s {, ` int a=0; //全局初始化区/ \- v3 w6 A/ y; w$ D: i $ ?) z3 w. z+ ~ char *p1; //全局未初始化区* T' n5 ^1 P- \* u! q main()' K9 ]2 g* h5 h9 @/ Z8 g { int b; //栈 , C1 r# t2 J0 W7 C2 S7 T char s[]="abc"; //栈, |& {- Y1 ^: o3 D) [ char *p3= "1234567"; //在文字常量区Flash 9 k. w! z/ ~$ ]& M static int c =0 ; //静态初始化区7 L# @8 C+ ]) s p1= (char *)malloc(10); //堆区" C* Y! }6 d" V strcpy(p1,"123456"); //"123456"放在常量区1 t4 d% h: W" a; j: O; D' i O6 _ $ {( q. `1 M/ U9 s: O$ ]9 o6 G }* y; [+ I$ C b6 j) L, Y+ K( N7 L 所以堆和栈的区别:, i$ G, |0 ~) F G 4 G$ @" r, b d% Q stack的空间由操作系统自动分配/释放,heap上的空间手动分配/释放。 stack的空间有限,heap是很大的自由存储区。. @ d8 `) x+ c. s4 Y6 x8 m ' P7 u- L( f3 e! G" c 程序在编译期和函数分配内存都是在栈上进行,且程序运行中函数调用时参数的传递也是在栈上进行。/ Y: c) m H( I! C t ( p8 o3 l- A# z P# h' t ------------------------------------------------------------------------------------------------------ 6 [- v$ `9 h6 o' C# F6 v3 y 1.堆和栈大小( t' {/ \/ y5 \8 ^5 x& e5 p2 i 定义大小在startup_stm32f2xx.s 4 j$ R. j. t1 ^; [4 e' \ Stack_Size EQU 0x00000400# [ B3 K! D4 y AREA STACK, NOINIT, READWRITE, ALIGN=3 8 H4 b9 Y# O6 @& B+ e5 V" N Stack_Mem SPACE Stack_Size __initial_sp' E1 u1 J9 ?) H ' B; z5 Y* l6 F8 \: f, ? ; Heap Configuration ; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ;+ i6 R+ g% N: P( J7 Y6 [ 3 @5 P: O5 M" Q5 j: |6 M Heap_Size EQU 0x00000200 5 i' h7 _2 J; ^3 u AREA HEAP, NOINIT, READWRITE, ALIGN=3 - R* L r4 M7 C- p4 \" h( \ __heap_base/ V3 |3 M! S% R5 [% v 2.堆和栈位置 通过MAP文件可知1 J# n. M/ I2 Q1 A HEAP 0x200106f8 Section 512 startup_stm32f2xx.o(HEAP) STACK 0x200108f8 Section 1024 startup_stm32f2xx.o(STACK); o% F, A3 [% W6 F 3 n6 }3 ?5 F- O: W' x: B __heap_base 0x200106f8 Data 0 startup_stm32f2xx.o(HEAP) 6 ~$ Z( d' [; J' R; Y __heap_limit 0x200108f8 Data 0 startup_stm32f2xx.o(HEAP) * {; _& ]+ i; @& A __initial_sp 0x20010cf8 Data 0 startup_stm32f2xx.o(STACK) 显然 Cortex-m3资料可知:__initial_sp是堆栈指针,它就是FLASH的0x8000000地址前面4个字节(它根据堆栈大小,由编译器自动生成)* s. r' P ^# i1 s( C/ R 2 A3 A; S( { }' @3 G 显然堆和栈是相邻的。 ![]() 3.堆和栈空间分配 " L- c" S. S7 I: P: x1 _% T 栈:向低地址扩展 堆:向高地址扩展 显然如果依次定义变量# F B- m+ O' _: R" g 先定义的栈变量的内存地址比后定义的栈变量的内存地址要大- R" y; ~0 B* w: T! J$ f- f/ D; K 3 S) o2 \- e1 n6 y0 g% F 先定义的堆变量的内存地址比后定义的堆变量的内存地址要小 4.堆和栈变量/ ]" O% }1 Y$ [" ? 栈:临时变量,退出该作用域就会自动释放 堆:malloc变量,通过free函数释放 ) o4 E% G1 \! P) ~- d$ r9 d 另外:堆栈溢出,编译不会提示,需要注意+ K2 Z; v7 @/ e/ V" H' L( W3 a! {' Y - q' e9 G$ }/ b# ^- J8 K5 q; { ------------------------------------------------------------------------------------------------------7 C5 f i# U6 E0 P/ b , X; H% L& n5 e# g R/ U 7 S& U/ D! y1 w' S' h% ~+ l " M. U e( a' w! D( Q 如果使用了HEAP,则必须设置HEAP大小。 0 r% b% N' k. L7 K 如果是STACK,可以设置为0,不影响程序运行。 IAR STM8定义STACK,是预先在RAM尾端分配一个字节的区域作为堆栈预留区域。 + i2 u7 P) D: K1 Y* \% Z 当程序静态变量,全局变量,或者堆与预留堆栈区域有冲突,编译器连接的时候就会报错。 你可以吧STACK设置为0,并不影响运行。(会影响调试,调试会报堆栈溢出警告)。 $ y; p2 a' L; O; S& { E" f# a; s% c 其实没必要这么做。 - b8 d E3 S# J0 n9 |. o 一般程序,(在允许范围内)设置多少STACK,并不影响程序真实使用的RAM大小, , Q) o! O p6 g# g8 A1 {( k# [ (可以试验,把STACK设置多少,编译出来的HEX文件都是一样), 程序还是按照它原本的状态使用RAM,把STACK设置为0,并不是真实地减少RAM使用。 仅仅是欺骗一下编译器,让程序表面上看起来少用了RAM。 而设置一定size的STACK,也并不是真的就多使用了RAM,只是让编译器帮你 2 V. y8 r& r" ?# X 检查一下,是否能够保证有size大小的RAM没有被占用,可以用来作为堆栈。 以上仅针对IAR STM8./ A5 U- r: Q) p% e2 e6 ^ ( D5 s; Y) A, ?' V5 [ ) ?1 U2 `6 b e3 A0 p# e ------------------------------------------------------------------------------------------------------" y# Q2 x3 f3 C& D " {1 H5 O8 u4 ^4 @ 从以上网摘来看单片机的堆和栈是分配在RAM里的,有可能是内部也有可能是外部,可以读写;5 _8 V/ _2 g. p4 }' f3 e 6 R$ k' u2 Z1 u" y" S8 s : x$ T3 P1 f0 W# H) b! |2 x 栈:存函数的临时变量,即局部变量,函数返回时随时有可能被其他函数栈用。所以栈是一种分时轮流使用的存储区,. e# l( d! U. _: k) H 编译器里定义的Stack_Size,是为了限定函数的局部数据活动的范围,操过这么范围有可以跑飞,也就是栈溢出; Stack_Size不影响Hex,更不影响Hex怎么运行的,只是在Debug调试时会提示错。栈溢出也有是超过了国界进行 活动,只要老外没有意见,你可以接着玩,有老外不让你玩,你就的得死,或是大家都死(互相撕杀),有的人写) |+ u% ]5 x. F& X2 Q: w* q a9 J 单片机代码在函数里定义一个大数组 int buf[8192],栈要是小于8192是会死的很惨。6 \, J; _! C/ d1 ] 堆:存的是全局变量,这变量理论上是所有函数都可以访问的,全局变量有的有初始值,但这个值不是存在RAM里的,是 & @# _$ ^) x- i& P1 \- n% }! w( b& r 存在Hex里,下载到Flash里,上电由代码(编译器生成的汇编代码)搬过去的。有的人很“霸道”,上电就霸占已一块很 ' V3 C6 u0 d. j6 {, k 大的RAM(Heap_Size),作为己有(malloc_init),别人用只能通过他们管家借(malloc),用完还得换(free)。所以 ' g* L6 U+ \0 V* G+ S2 E# b0 K 一旦有“霸道”的人出现是编译器里必须定义Heap_Size,否则和他管家借也没有用。* M* s1 _9 E4 s" i; p. s! n. |) J % t& u- O2 z3 R/ K8 X# D / W" o0 S/ \ F% I" H$ {. V* D7 E 总之:堆和栈有存在RAM里,他两各分多少看函数需求,但是他两的总值不能超过单片机硬件的实际RAM尺寸,否则只能* ?, Q( @1 ~' v" i8 H 到海里玩(淹死了)或是自己打造船接着玩(外扩RAM)。 |
stm32f207/stm32f407擦除内部flash讲解
【经验分享】STM32F2 中 DMA 的 FIFO 模式
STM32F2x7 通过以太网实现在应用中编程 (IAP)
STM32F2xx 微控制器中的 EEPROM 模拟
在 STM32 F0、 F2、 F3、 F4 和 L1 系列MCU 中使用硬件实时时钟 (RTC)
STM32F1xx、STM32F2xx、STM32F4xx、STM32L1xx、STM32F30/31/37/38x 定时器概览
使用 STM32F2xx 和 STM32F4xx 微控制器时如何提高 ADC 测量精度
使用 STM32F2 和 STM32F4 DMA 控制器
STM32F2x7 通过以太网实现在应用中编程 (IAP)
STM32F2xx 微控制器中的 EEPROM 模拟