堆 栈 段的一些基础知识

段 堆 栈

(segmentation)

指二进制文件内的区域,所有某种特定类型的信息被保存在里面

tips:在.exe中,正文段(Text segmentation)用于存储指令,数据段(Data Segmentation)用于储存已初始化的全局变量,BBS段用于存储未赋值的全局变量。

调用栈所在的段叫做堆栈段

堆(heap)

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

堆用来容纳应用程序动态分配的内存区域,我们使用malloc 或者new分配内存时,得到的内存来自堆里。堆通常存于栈的下方(低地址方向),堆一般比栈大很多,可以有几十至数百兆字节的容量。

栈 (stack)

栈又称堆栈,是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。

栈用于维护函数调用的上下文,离开栈函数调用就会无法实现。栈通常在用户空间的最高地址处分配,通常有数兆字节。

栈的大小

linux中栈的大小由系统命令ulimit决定

windows中栈大小存储在可执行文件中 在gcc中这样指定:

gcc-W1,--stack=16777216这样栈就有16mb啦

堆栈段也有大小,越界访问会出现段错误

由于调用栈被填满导致的越界叫栈溢出(Stack Overflow)

调用栈(Call Stack)

假设 A 调用 B,B 再调用 C,C 执行完返回给 B,B 再执行完返回给 A,哪种数据结构最适合管理它们所使用的内存?没错,是 stack,因为过程调用具有 last-in first-out 的特点。当 A 调用 B 的时候,A 只要将它需要传递给 B 的参数 push 进这个 stack,再把将来 B 返回之后 A 应当继续执行的指令的地址(学名叫 return address)也 push 进这个 stack,就万事大吉了。之后 B 可以继续在这个 stack 上面保存一些寄存器的值,分配局部变量,进而继续构造调用 C 时需要传递的参数等等。

这个 stack 其实就是我们所说的 call stack。(这里的描述有些简化,实际当中计算机会做一些优化,如果参数和局部变量不太多的话就懒得放在 call stack 里,而是直接使用寄存器了。)

Call stack 在 virtual memory 里其实就是一段连续的地址空间,靠一个叫做 SP 的寄存器(32-bit 叫 ESP,64-bit 叫 RSP)来指向栈顶。既然是连续的,于是它在使用上比我们理论课上讲的抽象的 stack 要更灵活一些,更接近 array 而不是 linked list,可以访问任意元素,而不仅仅是栈顶元素。(当然进栈出栈还是只能在栈顶进行。)这也就是为什么尽管它叫做 call stack,我们依然可以同时有不止一个参数和不止一个局部变量的原因。

调用栈在运行时创建

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇