学习交流加
- 个人qq:
1126137994- 个人微信:
liu1126137994- 学习交流资源分享qq群:
962535112
在我之前学习底层的知识的时候,也写过相关的内容。可以对比的学习:【软件开发底层知识修炼】二十 深入理解可执行程序的结构,【软件开发底层知识修炼】二十三 ABI-应用程序二进制接口三之深入理解函数栈帧的形成与摧毁
文章目录
- 1 程序中的栈内存结构
- 1.1 函数的调用过程对应的栈的变化
- 1.11 函数调用栈上的数据
- 2 程序中(应该称为进程中才对)的堆结构
- 3 程序中的静态存储区(其实就是数据区)
- 4 总结
1 程序中的栈内存结构
- 栈在程序中用于维护函数调用的上下文
- 函数中的参数和局部非静态变量存储在栈上
- esp指针始终指向栈顶
- ebp是函数栈帧,用于定位的,使用ebp可以查找到函数的参数,返回地址等信息。后面的函数调用分析会认识到这一点
- 栈在整个进程内存空间中是从上往下扩展,也就是从高地址往低地址扩展。如下图是一个栈
1.1 函数的调用过程对应的栈的变化
每次函数调用都对应一个栈上的活动记录,被调用函数的活动记录位于调用函数的下面。比如有如下的几个函数调用:
注意:上面的栈中的内容并没有具体,只是说明各个函数的活动记录信息在哪个文职,具体里面的内容没有列出。看下面的分析:
从程序开始运行时分析:
- 从main函数开始运行
当main开始运行的时候,main函数的栈的信息是下面这样的:
- f函数的参数先入栈
- 然后返回地址入栈(main函数调用f()函数那里的地址)
- 然后main函数的ebp的地址入栈。用于定位上一个函数的ebp
f函数调用g函数就是一样的过程,这里就不再赘述。下面直接上当f执行完返回的过程是怎样的/p>
- 当从f()调用中返回到main函数的栈的变化
2 程序中(应该称为进程中才对)的堆结构
- 堆空间是进程的内存空间中一块预留的内存空间,供程序在运行的时候动态分配。
- 使用malloc与free进行堆中的内存的动态申请(具体的使用可以参考这篇文章:【C语言进阶深度学习记录】三十三 C语言中动态内存分配
操作系统对堆的管理方式主要有:
- 空闲链表法、位图法、对象池法
下面主要简要说明空闲链表发的原理:
空闲链表就是操作系统将整个可用的堆内存空间分为一块一块的,对应的相同数量的指针指向各个内存块,然后内存块的末尾又是一个指针指向下一个内存块的头。
其实简单来说就是将多个内存块串联成一个链表形式。
如下图所示:
我们已经看到了上图中,它们在可执行文件中都是存储在.data区,.bss区。这些区域。
当程序运行起来之后,它们还是会在进程的内存空间的.data与.bss段。与可执行文件的data与bss名字一样如下图

我们称之为静态存储区。为什么叫静态不是因为static,而是因为它们的值虽然有可能被改变,但是却一直在那个区域。不像栈区域的值最后会被销毁,堆上的值也需要free。
现在终于明白静态存储区实际就是.data与.bss区域了。
下面总结一下静态存储区的几点重要知识:
- 静态存储区是随着程序的运行而分配空间
- 静态存储区的生命周期直到程序运行而结束
- 在程序的编译期间,静态存储区的大小就已经确定
- 静态存储区主要用于保存全局变量和静态局部变量以及类似于字符串字面量样式的字面量
4 总结
栈,堆与静态存储区是进程地址空间的基本数据区域。
- 一定要注意区分可执行文件中的内容与程序运行起来后的进程地址空间中的内容的差别。
文章知识点与官方知识档案匹配,可进一步学习相关知识C技能树进阶任务C语言问答113477 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!