c函数调用过程
一、内存结构
内存大致可以分为四个部分:代码段,静态存储区,堆,栈。
具体划分如下图所示:
栈:在执行函数时,函数内部局部变量的存储单元都可以在栈上创建,函数执行结束后会自动释放内存。栈内存的分配运算内置于处理器的指令中。效率高,但分配的内存容量有限,程序发生错误时,很有可能出现栈溢出。
堆:又称为动态内存分配区,程序在执行的时候用malloc或new申请指定大小的内存,程序员自己负责在任何时候用free或delete释放内存。若在申请后未释放,在程序结束时有可能会有OS自动回收,或者造成内存泄露,因此,使用时一定要注意。
静态存储区:包括程序中明确被初始化的全局变量、静态变量、常量以及未被初始化的数据。内存在程序编译时已经分配好,这块内存在整个运行期间一直存在。
代码区:存放程序代码,代码区是可以共享的(其他的执行程序可以调用它),整个内存中只有一份。
栈和堆的区别
1.管理方式不同
栈由编译器自动管理,堆由程序员控制。
2.空间大小不同
栈是向低地址扩展的结构,是连续的内存区域,因此栈顶和栈底是规定好的,容量有限,若用户使用过多的栈空间,会产生溢出。堆是向高地址扩展,不是连续的内存区域,堆获得的空间较大,分配时也比较灵活。
3.是否产生碎片
对于堆来说,频繁的malloc/free,new/delete会是空间不连续,造成大量碎片,使得程序效率降低。而栈不存在这样的问题。
4.增长方向不同
堆和栈相对生长
5.分配方式
堆由程序员通过使用malloc、free、new、delete来进行管理。栈由编译器申请释放,栈的动态内存分配通过alloca函数完成。
6.分配效率不同
栈是机器系统提供的数据结构,计算机在底层对栈提供支持。堆是C库函数提供的,堆的效率比栈低得多。
二、函数的调用过程(栈帧)
每一次的函数调用都是一个过程,我们将这个过程称为函数的调用过程。在这个过程中,会开辟栈空间用来保存本次函数调用过程中临时变量以及现场保护等工作,这块栈空间我们称之为函数栈帧。栈帧的维护需要两个寄存器也叫帧指针,即ebp和esp,esp中存放栈顶地址,ebp存放栈底地址。esp和ebp一次只能存放一个地址。
以下是函数调用的详细过程:
假设函数a调用了函数b,函数b调用了函数c,函数b有三个参数,从左至右依次为参数1,参数2,参数3。
1.函数a在调用函数b的时候,首先将函数b的参数以相反的顺序依次压入栈中,即,从最后一个参数开始压栈。
2.函数a使用call指令调用函数b,并将call指令下的一条指令的地址当做返回地址压入栈中。(汇编call命令的两个功能:1.保存当前指令的下一个指令的地址。2.pc指针跳转到调用函数的入口地址。)
3.在函数b的栈帧中,首先保存函数a的栈底地址,再将函数a的栈顶地址当做函数b的栈底地址,即图中所示的push ebp和mov ebp,esp这两条指令。
4.然后,从ebp的位置开始存放函数b的局部变量,将这些变量的地址依次存放在栈中,先定义的先入栈,后定义的后入栈。
注意:在不同的编译器上函数的调用过程可能会有所不同,但大致思想相同。
汇编的堆栈操作指令
1:栈是自顶向下生长
2:栈是先入后出的数据结构
3:push会使esp-4
4:pop会使esp+4
临时存放数据
传递参数
保存和恢复寄存器 PUSHF/POPF
c函数调用过程的更多相关文章
- 从一个新手容易混淆的例子简单分析C语言中函数调用过程
某天,王尼玛写了段C程序: #include <stdio.h> void input() { int i; ]; ; i < ; i++) { array[i] = i; } } ...
- c函数调用过程原理及函数栈帧分析
转载自地址:http://blog.csdn.net/zsy2020314/article/details/9429707 今天突然想分析一下函数在相互调用过程中栈帧的变化,还是想尽量以比 ...
- 函数调用过程&生成器解释
摘自马哥解答,感谢. 函数调用过程: 假设程序是单进程,单执行流,在某一时刻,能运行的程序流只能有一个.但函数调用会打开新的执行上下文,因此,为了确保main函数可以恢复现场,在main函数调用其它函 ...
- Linux驱动调试-根据oops的栈信息,确定函数调用过程
上章链接入口: http://www.cnblogs.com/lifexy/p/8006748.html 在上章里,我们分析了oops的PC值在哪个函数出错的,那如何通过栈信息来查看出错函数的整个调用 ...
- C语言的函数调用过程
从汇编的角度解析函数调用过程 看看下面这个简单函数的调用过程: int Add(int x,int y) { ; sum = x + y; return sum; } int main () { ; ...
- 37.Linux驱动调试-根据oops的栈信息,确定函数调用过程
上章链接入口: http://www.cnblogs.com/lifexy/p/8006748.html 在上章里,我们分析了oops的PC值在哪个函数出错的 本章便通过栈信息来分析函数调用过程 1. ...
- 深入理解C语言的函数调用过程 【转】
转自:http://blog.chinaunix.net/uid-25909619-id-4240084.html 原文地址:深入理解C语言的函数调用过程 作者:wjlkoorey258 本文 ...
- C语言的函数调用过程(栈帧的创建与销毁)
从汇编的角度解析函数调用过程 看看下面这个简单函数的调用过程: int Add(int x,int y) { ; sum = x + y; return sum; } int main () { ; ...
- C++函数调用过程深入分析<转>
转自http://blog.csdn.net/dongtingzhizi/article/details/6680050 C++函数调用过程深入分析 作者:靠谱哥 微博:洞庭之子-Bing 0. 引言 ...
- 用systemtap跟踪打印动态链接库的所有c++函数调用过程
http://gmd20.blog.163.com/blog/static/168439232015475525227/ 用systemtap跟踪打印动态链接库的所有c++函数 ...
随机推荐
- vue中引入静态图片
vue+webpack中,可以使用require imageList: [ { url: require('../image/pig.png') } ] vue+vite没有require方法 // ...
- js获取浏览器宽度和高度值
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>请调整浏览器窗口</t ...
- 制造业常用KPI
1. 质量KPI CA (Capability of Accuracy): 平均值距离期望中心值的距离,值越大,说明平均值越接近期望中心值. Ca=(X-U)/(T/2) CP (Capabilit ...
- [转载]危险操作一追到底--Linux的历史记录
转自:https://zhuanlan.zhihu.com/p/524921170 危险操作一追到底--Linux的历史记录 KellanFan 为了更好的自己 概述 在Linux下使用his ...
- 2、flex最后不对齐问题
https://www.zhangxinxu.com/wordpress/2019/08/css-flex-last-align/
- py2exe打包datatable程序后运行时提示No module named 'datatable.utils'
把setup.py的代码更新为如下: setup(console=['test1.py'], options={ 'py2exe':{ 'packages':['datatable.utils'] } ...
- Linux系统下追加记录到文件中的实例代码解读
今日阅读Linux程序设计第四版,找到一个使用mmap函数的实例 问题描述 该程序主要定义一个结构体,随后利用mmap,msync以及munmap函数对其进行内容追加,定位以及修改内容的操作. 先自己 ...
- 04-python垃圾回收机制
python垃圾回收机制 一.引入 解释器在执行定义变量的语法时,会申请内存空间来存放变量值,每一块内存空间都有其唯一的内存地址,我们在前面说过,变量名并不是存放的变量值,而是存放的内存地址,通过访问 ...
- Centos7提示Initial setup of CentOS Linux 7 (core)
Initial setup of CentOS Linux 7 (core) 1) [x] Creat user 2) [!] License information (no user will be ...
- vue移动端禁止弹层穿透、点击元素滚动到视图中心杂文日志
一,需求是在无限列card加载页面,点击任何一个card的显示图表按钮,图表自适应居中显示,显示遮罩层,页面可以滑动,但不能穿透点击 一个无限列表加载页面设置遮罩层一般需求是页面不能滑动的,但这比较特 ...