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语言函数栈帧内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用C语言编写一个强制关机程序

    使用C语言编写一个强制关机程序

    这篇文章主要为大家详细介绍了如何使用C语言实现一个简单的"流氓软件",一个可以强制关机恶作剧关机程序,输入指定指令才可以解除,感兴趣的小伙伴可以学习一下
    2023-11-11
  • C++中对象的赋值与复制操作详细解析

    C++中对象的赋值与复制操作详细解析

    对象之间的赋值也是通过赋值运算符“=”进行的。本来赋值运算符“=”只能用来对单个的变量赋值,现在被扩展为两个同类对象之间的赋值,这是通过对赋值运算符的重载实现的
    2013-10-10
  • c语言打开文件函数使用方法

    c语言打开文件函数使用方法

    这篇文章主要介绍了c语言打开文件函数使用方法,需要的朋友可以参考下
    2014-02-02
  • C语言修炼之路数据类型悟正法 解析存储定风魔上篇

    C语言修炼之路数据类型悟正法 解析存储定风魔上篇

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2022-02-02
  • C++基于easyx图形库实现打砖块游戏

    C++基于easyx图形库实现打砖块游戏

    这篇文章主要为大家详细介绍了C++基于easyx图形库实现打砖块游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • C++中类的成员函数及内联函数使用及说明

    C++中类的成员函数及内联函数使用及说明

    这篇文章主要介绍了C++中类的成员函数及内联函数使用及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C语言嵌入informix基础入门示例讲解

    C语言嵌入informix基础入门示例讲解

    这篇文章主要介绍了C语言嵌入informix基础方法,大家参考使用
    2013-11-11
  • C++简明分析讲解引用与函数提高及重载

    C++简明分析讲解引用与函数提高及重载

    今天继续开始对C++核心编程知识的分享与系统讲解,第一,这里会提到“引用”方法传参以及剖析引用的本质;第二,我们对函数来一个提高,相当于进阶函数了,包括函数的默认值,简单的提一下函数的占位参数,函数重载以及注意事项,接下来上正文
    2022-05-05
  • VScode上配置 c语言环境的图文教程

    VScode上配置 c语言环境的图文教程

    这篇文章主要介绍了配置VScode c语言环境,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05

最新评论