简述内存管理

101 阅读4分钟

​开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情

 大家一定知道堆和栈吧。首先,我们来说一下堆和栈的区别:

1.堆栈空间分配的方式不同。栈由操作系统自动分配释放,存放函数的参数值,局部变量的值等等;而堆一般由程序员分配释放。

2.堆栈缓存方式不同。栈使用的是一级缓存,它们通常都是被调用时处于存储空间中,调用完毕之后立即释放;堆则是存放在二级缓存之后,速度要慢些。

3.堆栈数据结构不同。堆类似于数组;栈类似数据结构中的栈结构,是先进后出的。

内存管理: 

   对于一个C语言程序而言,内存空间主要由五个部分组成,分别为代码段(.text)、数据段(.data)、BSS段(.bss)、堆和栈组成。其中代码段、数据段和BSS段是编译的时候由编译器分配的,而堆和栈是程序运行的时候由操作系统分配的。

1.数据段:存放程序中已初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量)的区域。

2.代码段:存放程序执行代码的一块内存区域。只读,为了防止程序意外地修改了它的指令。另外,还会包含一些只读常数变量。

3.未初始化数据段(BSS段) :存放的是程序中未初始化的全局变量和静态变量

4.可执行程序在运行时又会分为两个区域:栈区和堆区

栈区:存储局部变量、函数参数值以及在进行任务切换时存放当前任务的上下文内容。栈从高地址向低地址增长。是一块连续的空间。

堆区:用于动态内存分配。位于BSS段和栈之间。它的大小并不固定,可动态扩张或者缩减。

     在将应用程序加载到内存空间执行的时候,操作系统负责代码段、数据段和BSS段的加载,并将在内存中为这些段分配空间。栈亦由操作系统分配和管理,堆由程序员自己管理,即显式的地申请和释放空间。

image.png

下面,我们来说一下程序启动的过程:

     1.操作系统首先创建相应的进程并分配私有的进程空间,然后由操作系统的加载器负责,把可执行文件的数据段和代码段映射到进程的虚拟内存空间中去。

     2.加载器读入可执行程序的导入符号表,根据这些符号表可以查找出该可知行文件的所有依赖的动态链接库。

    3. 加载器针对该程序的每一个动态链接库调用LoadLibrary函数:

(1)查找对应的动态库文件,加载器为该动态链接库确定一个合适的基地址。

(2)加载器读取该动态链接库的导入符号和导出符号表,比较应用程序要求的导入符号表和导出符号表,比较应用程序要求的导入符号是否匹配该库的导出符号表。

(3)针对该库的导入符号表,查找对应的依赖动态连接库的初始化函数。

(4)调用该动态来凝结库的初始化函数。

     5.初始化应用程序的全局变量,对于全局对象自动调用构造函数。

     6.进入应用程序如入口点,函数开始执行。

符号表:用于语言翻译器中的数据结构。在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如数据类型、作用域和内存地址。

LoadLibrary函数:将指定的模块加载到调用进程的地址空间中。