开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
大家一定知道堆和栈吧。首先,我们来说一下堆和栈的区别:
1.堆栈空间分配的方式不同。栈由操作系统自动分配释放,存放函数的参数值,局部变量的值等等;而堆一般由程序员分配释放。
2.堆栈缓存方式不同。栈使用的是一级缓存,它们通常都是被调用时处于存储空间中,调用完毕之后立即释放;堆则是存放在二级缓存之后,速度要慢些。
3.堆栈数据结构不同。堆类似于数组;栈类似数据结构中的栈结构,是先进后出的。
内存管理:
对于一个C语言程序而言,内存空间主要由五个部分组成,分别为代码段(.text)、数据段(.data)、BSS段(.bss)、堆和栈组成。其中代码段、数据段和BSS段是编译的时候由编译器分配的,而堆和栈是程序运行的时候由操作系统分配的。
1.数据段:存放程序中已初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量)的区域。
2.代码段:存放程序执行代码的一块内存区域。只读,为了防止程序意外地修改了它的指令。另外,还会包含一些只读常数变量。
3.未初始化数据段(BSS段) :存放的是程序中未初始化的全局变量和静态变量。
4.可执行程序在运行时又会分为两个区域:栈区和堆区
栈区:存储局部变量、函数参数值以及在进行任务切换时存放当前任务的上下文内容。栈从高地址向低地址增长。是一块连续的空间。
堆区:用于动态内存分配。位于BSS段和栈之间。它的大小并不固定,可动态扩张或者缩减。
在将应用程序加载到内存空间执行的时候,操作系统负责代码段、数据段和BSS段的加载,并将在内存中为这些段分配空间。栈亦由操作系统分配和管理,堆由程序员自己管理,即显式的地申请和释放空间。
下面,我们来说一下程序启动的过程:
1.操作系统首先创建相应的进程并分配私有的进程空间,然后由操作系统的加载器负责,把可执行文件的数据段和代码段映射到进程的虚拟内存空间中去。
2.加载器读入可执行程序的导入符号表,根据这些符号表可以查找出该可知行文件的所有依赖的动态链接库。
3. 加载器针对该程序的每一个动态链接库调用LoadLibrary函数:
(1)查找对应的动态库文件,加载器为该动态链接库确定一个合适的基地址。
(2)加载器读取该动态链接库的导入符号和导出符号表,比较应用程序要求的导入符号表和导出符号表,比较应用程序要求的导入符号是否匹配该库的导出符号表。
(3)针对该库的导入符号表,查找对应的依赖动态连接库的初始化函数。
(4)调用该动态来凝结库的初始化函数。
5.初始化应用程序的全局变量,对于全局对象自动调用构造函数。
6.进入应用程序如入口点,函数开始执行。
符号表:用于语言翻译器中的数据结构。在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如数据类型、作用域和内存地址。
LoadLibrary函数:将指定的模块加载到调用进程的地址空间中。