内存分区(堆栈作用)

0. 目录

1. 结论

直接给结论:

  1. stack栈
  2. heap堆
  3. bss
  4. data
  5. text

1.1 作用

  1. stack栈
    存放局部非静态变量,用来保存现场(堆栈作用)
    从高地址向低地址生长。
  2. heap堆
    存放malloc和new开的内存
  3. bss
    Block Started by Symbol,存放全局未初始化变量,静态变量。
    bss不占实际的磁盘空间,运行时分配内存。编译的可执行文件中不包含这部分。
  4. data
    data segment,存放已初始化的全局变量,已初始化的静态变量
  5. text
    code segment/text segmen,存放系统代码,只读区域

1.2 位置

五大内存分区的位置如下图:

内存分区
text和data段,为编译可执行文件时确定,

2. 疑问

其实之前看了不少文章,但是感觉大家的分类都不一致。
简单来说,观点比较一致的如下:

  • 5大分区
  • 堆+栈是一定有的

其他的部分感觉名称各式各样:
全局区、静态区、文字常量区、 自由存储区、常量存储区…

看着看着,真的问题越来越多:

  • 是不是不同C语言和C++语言(或者其实是跟着编译器走的?),是不一致的,所以大家有各自的分法?
  • 是不是win和linux不一样,所以大家总是能给出各种花式答案?
  • 字符串常量(只读数据段) 是属于代码段 .text 还是数据段 .data ?(未解决)
  • 编译出来的可执行文件?包含了哪几部分?

2.1 名词解释

  • 全局区
    就是数据段
  • 静态区
    就是数据段
  • 文字常量区
    就是rodata段,不知道划分为数据段还是代码段。看名字是数据段,但是性质又和代码段一样(不可改)
  • 常量存储区
    同rodata段
  • 自由存储区
    网上找的是说,new开的,free关的部分,有点疑惑,这个不应该是堆吗?或者C++规定不同。

2.2 混淆概念

其实怎么分区,按照链接文件来看最清晰了。
其他的分区无非是定义的混淆和重定义。
在ld文件中,明确的就是
.data段
.bss段
.text段
有些文章就把.data段分成了常量区+数据区
有些文章把数据区作为data+bss的统称
有些文章把常量字符串放入了代码段

3. 堆栈

看完了内存分区,主要再总结一下堆栈作用,其实主要还是栈。

3.1 混淆概念

之前看过一些话:

  • 一个线程只有一个栈
  • 每次函数调用有一个栈
  • 每个进程有两个栈,内核栈+用户栈

所以,到底是几个栈?

3.2 概念


  • 栈是一种先进后出(FILO)的数据结构
  • 系统栈/调用栈
    (Call stack),是整个栈空间,由栈帧组成。
  • 栈帧
    (stack frame), 每一个函数独占自己的栈帧空间。当前正在运行的函数的栈帧总是在栈顶。Win32系统提供两个特殊的寄存器用于标识位于系统栈顶端的栈帧。
  1. ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
  2. EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。

3.3 函数调用过程

函数调用主要是依靠栈来实现现场的保护,函数的重入等等。
在这里插入图片描述

3.3.1 调用过程

  1. 参数入栈: 将参数按照调用约定(C 是从右向左)依次压入系统栈中;
  2. 返回地址入栈: 将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行;
  3. 代码跳转: 处理器将代码区跳转到被调用函数的入口处;
  4. 栈帧调整:
    1. 将调用者的ebp压栈处理,保存指向栈底的ebp的地址(方便函数返回之后的现场恢复),此时esp指向新的栈顶位置; push ebp
    2. 将当前栈帧切换到新栈帧(将eps值装入ebp,更新栈帧底部), 这时ebp指向栈顶,而此时栈顶就是old ebp mov ebp, esp
    3. 给新栈帧分配空间 sub esp, XXX

3.3.2 返回过程

  1. 保存被调用函数的返回值到 eax 寄存器中 mov eax, xxx
  2. 恢复 esp 同时回收局部变量空间 mov ebp, esp
  3. 将上一个栈帧底部位置恢复到 ebp pop ebp
  4. 弹出当前栈顶元素,从栈中取到返回地址,并跳转到该位置 ret

4. 验证实验

待补充,汇编分析

参考链接

函数调用
系统栈的工作原理
Linux内存分区---------介绍比较详细,就是把rodata划入了代码区,不知道对不对

发布了25 篇原创文章 · 获赞 7 · 访问量 5119

猜你喜欢

转载自blog.csdn.net/tao475824827/article/details/102903183