C语言函数栈帧的创建与销毁详解

 更新时间:2022年09月08日 12:06:10   作者:保护小周ღ  
函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,下面这篇文章主要给大家介绍了关于C语言函数栈帧的创建与销毁的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

前言

C语言,我们学到了这里,一定会有许多疑惑,我们的代码逻辑,定义的变量,自定义的函数等通过编译器,准确的来讲是集成开发环境(vs),预处理、编译、汇编、链接,在电脑上执行的过程中,计算机内部到底是怎么运行的,我们要搞清楚这些基础的过程,而不是说,因为这样做,所以有什么样的结果,过程是怎么样的,我们一概不了解,这样学编程是不对的,要刨根问底,增强自己的内功。保姆级讲述包您一看就会,快来试试吧~

举个例子:

int main()
{
    int a=0;
    return 0;
}

根据以上代码,我们可以读出一段信息,定义一个局部整型变量 a,并将他初始化为0,同时一个整型变量在内存中占4个字节。关于main()函数的返回值啊,简单说一下,如果返回值为0,则说明程序是正常结束,非0,就是不正常结束,且返回值为整型数据。

那么博主在这里问大家两个问题:

  • 局部整型变量a,到底是怎么创建的?
  • 如果我们对变量a不进行初始化操作,局部变量a的值是多少?
  • main()函数也有返回值,那他是不是也是也被其他函数调用?

函数在调用的过程中栈帧的创建和销毁对于不同的编译器来说略有差异,但大体的逻辑是差不多的。取决于编译器。

 什么是函数栈帧?

 每一次函数的调用,操作系统都会在内存的栈区上开辟一块空间,称为栈帧。

函数调用建立栈帧,栈帧中存储局部变量,参数等等。

 

栈区,堆区等是操作系统这门学科中对内存的划分,数据结构的“栈”,“堆”是存放、处理数据的一种结构,跟内存的栈区,堆区,没有啥关系,但是有一点,数据结构的“栈”和内存的栈区都是后进先出,先进后出的特性。

 举个例子:

在main() 函数内部的Sum()函数则是被 main()函数调用,Sum()函数结束开辟的栈帧被操作系统回收,返回mian()函数的Sum()函数调用点,继续执行程序。

程序顺序执行 ,执行main()函数,遇到 int a=1; 操作系统就会在内存的栈区上,为main()函数创建栈帧里,给局部变量 a 分配一块4个字节的空间。同理,局部变量在那个函数里创建的,那么就在那个函数的栈帧中为其分配空间。函数在调用的时候操作系统会为函数预划分一片空间,就是所谓的栈帧,由 esp,ebp 两个寄存器维护,如果空间不够了,操作系统会在这片空间的栈顶(esp)增加空间入栈,esp 可以动态的维护栈顶。

知识点普及:

局部变量是在内存的栈区上开辟的,栈区内存的使用习惯是先使用高地址的空间,后使用低地址的空间,栈区又是一种先进后出,后进先出的结构,且只能在一端操作。

在为函数创建栈帧的时候,会有很多的寄存器去维护,这一片的可使用空间就会被初始化为随机值,这个根据不同的编译器有不同的初始化方式,这就是我们对局部变量定义的时候不进行初始化打印随机值的原因。

 由图可见,栈底寄存器 ebp-0E4h 就等于 edi 指向的空间。

不过现在的编译器很智能,如果没有初始化局部变量使用的话会报错,就很强,但是大家还是要养成良好的初始化的习惯。

Sum() 函数的调用  

传参:

把变量a,b 的值分别存储在 ecx ,eax 寄存器,分别入栈。就相当于使用两块空间 又将a,b 存储了一次。这就是形参嘛。

形参是实参的拷贝!这段形参开辟的空间实际上还是在main() 函数的栈帧中。esp 栈顶指针动态维护。

esp ,edp 如何从main() 栈帧,来维护 Sum() 函数栈帧:

 区间实际上是(ebx,ebp)

 return 会返回 call 指令的这个地址,可以继续执行程序。

C/C++ 程序内存分配的几个区域:

1.栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限,栈区主要存放运行函数而分配的局部变量,函数参数,返回数据,返回地址等。

2.堆区(heap):一般由程序员分配释放,若程序员不释放,程序结束时由OS回收。

3.数据段(静态区)(static)存放全局变量,静态变量。程序结束后由系统释放。

4.代码段:存放函数体(类成员函数和全局函数)的二进制代码

至此C语言函数栈帧的创建和销毁博主已经分享完了,相信大家对这个函数怎么建立的、销毁的,函数怎么传参,使用等有了一定的理解,大家可以自己使用汇编代码,感受一下。

总结

到此这篇关于C语言函数栈帧的创建与销毁的文章就介绍到这了,更多相关C语言函数栈帧内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解在VScode中添加代码块(含C++指令生成代码)

    详解在VScode中添加代码块(含C++指令生成代码)

    这篇文章主要介绍了详解在VScode中添加代码块(含C++指令生成代码),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • C++通过自定义函数找出一个整数数组中第二大数的方法

    C++通过自定义函数找出一个整数数组中第二大数的方法

    这篇文章主要介绍了C++通过自定义函数找出一个整数数组中第二大数的方法,涉及C++针对数组的遍历操作相关技巧,需要的朋友可以参考下
    2015-06-06
  • 7种排序算法的实现示例

    7种排序算法的实现示例

    这篇文章主要介绍了7种排序算法的实现示例,需要的朋友可以参考下
    2014-05-05
  • OpenCV实现图像去噪算法的步骤详解

    OpenCV实现图像去噪算法的步骤详解

    这篇文章主要为大家介绍了OpenCV中图像去噪算法的原理,文中通过示例为大家详细讲解了图像去噪算法的使用,感兴趣的小伙伴可以了解一下
    2022-06-06
  • C++中的String的常用函数用法

    C++中的String的常用函数用法

    这篇文章主要介绍了C语言中String的常用函数用法,对学习String的小伙伴有一定的参考价值,感兴趣的小伙伴可以借鉴一下
    2023-03-03
  • C++实现五子棋游戏(注释版)

    C++实现五子棋游戏(注释版)

    这篇文章主要为大家详细介绍了C++实现五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • VSCode如何使用最新的C++20(推荐)

    VSCode如何使用最新的C++20(推荐)

    这篇文章主要介绍了VSCode使用最新的C++20的相关知识,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • C语言实现扫雷游戏附注释

    C语言实现扫雷游戏附注释

    这篇文章主要为大家详细介绍了C语言实现扫雷游戏附注释,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • C语言实现简易扫雷游戏详解

    C语言实现简易扫雷游戏详解

    这篇文章主要为大家详细介绍了C语言实现简易扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • C++实现判断字符串是否回文实例解析

    C++实现判断字符串是否回文实例解析

    这篇文章主要介绍了C++实现判断字符串是否回文,其中采用了数据结构中栈以及过滤字符等技术,,需要的朋友可以参考下
    2014-07-07

最新评论