首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

对于函数调用,调用堆栈展开过程到底是如何工作的?- C++

函数调用的调用堆栈展开过程是指在程序执行过程中,当一个函数被调用时,系统会将当前函数的执行上下文(包括局部变量、函数参数、返回地址等)保存在堆栈中,然后跳转到被调用函数的代码执行。当被调用函数执行完毕后,系统会从堆栈中恢复上一个函数的执行上下文,并继续执行上一个函数的代码。

具体的调用堆栈展开过程如下:

  1. 当一个函数被调用时,系统会将当前函数的返回地址、函数参数和局部变量等信息保存在堆栈中,同时将控制权转移到被调用函数的代码处。
  2. 被调用函数开始执行,根据函数的定义,执行相应的操作。
  3. 如果被调用函数中调用了其他函数,系统会将当前函数的执行上下文保存在堆栈中,并跳转到被调用函数的代码处。
  4. 被调用函数执行完毕后,系统会从堆栈中恢复上一个函数的执行上下文,并继续执行上一个函数的代码。
  5. 当最后一个函数执行完毕后,系统会从堆栈中恢复主函数的执行上下文,程序结束。

调用堆栈展开过程的工作原理是通过使用栈来保存函数的执行上下文,每次函数调用都会在栈上分配一块内存空间,用于保存函数的返回地址、参数和局部变量等信息。当函数执行完毕后,系统会将栈顶指针恢复到上一个函数的位置,从而实现函数调用的返回和继续执行上一个函数的代码。

函数调用的调用堆栈展开过程在C++中是由编译器和操作系统共同完成的。编译器负责生成函数调用和返回的代码,将函数的执行上下文保存在堆栈中;操作系统负责管理堆栈的分配和恢复,确保函数调用的正确执行。

函数调用的调用堆栈展开过程在软件开发中非常重要,它可以帮助我们理解函数调用的执行顺序和上下文切换的过程。在调试程序时,我们可以通过查看调用堆栈来追踪函数的执行路径,定位问题所在。此外,了解调用堆栈展开过程还有助于优化程序的性能,避免不必要的函数调用和堆栈操作。

对于C++语言,腾讯云提供了云函数(SCF)服务,它是一种无服务器计算服务,可以帮助开发者在云端运行代码,无需关心服务器的管理和维护。云函数支持多种编程语言,包括C++,可以通过编写函数代码并配置触发器来实现函数的调用和执行。您可以参考腾讯云云函数的官方文档了解更多信息:腾讯云云函数

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

JavaScript如何工作:引擎,运行时和调用堆栈概述

这篇文章旨在成为系列中第一个旨在深入挖掘JavaScript及其实际工作系列文章:我们认为,通过了解JavaScript构建方式以及它们如何协同构建,您将能够编写更好代码和 应用。...如果我们进入一个函数,我们在堆栈顶部。 如果我们从一个函数返回,我们从堆栈顶部弹出。 这就是堆栈可以做。 我们来看一个例子。...然而,这个函数是递归,并且开始调用自身而没有任何终止条件。 所以在执行每个步骤中,相同功能被一次又一次地添加到调用堆栈中。 看起来像这样: ?...然而,在某些时候,调用堆栈函数调用次数超过了调用堆栈实际大小,并且浏览器决定采取行动,通过抛出一个错误,看起来像这样: ?...这将在“JavaScript如何实际工作”教程第2部分中更详细地解释:“V8引擎内有关如何编写优化代码5个提示”。

1.8K40

C++如何禁止函数传值调用

代码编译运行环境:VS2017+Debug+Win32 ---- 按照参数形式不同,C++应该有三种函数调用方式:传值调用、引用调用和指针调用。...对于基本数据类型变量作为实参进行参数传递时,采用传值调用与引用调用和指针调用效率相差不大。但是,对于类类型来说,传值调用和引用调用之间区别很大,类对象尺寸越大,这种差别越大。...传值调用与后面两者区别在于传值调用在进入函数体之前,会在栈上建立一个实参副本,而引用和指针调用没有这个动作。建立副本操作是利用拷贝构造函数进行。...这样就能阻止了函数调用时,类A对象以值传递方式进行函数函数调用。...---- 参考文献 [1]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.[3.5(P102-P103)] [2]拷贝构造函数什么时候调用

2.4K30
  • JavaScript是如何工作:引擎,运行时和调用堆栈概述!

    本文是旨在深入研究JavaScript及其实际工作原理系列文章中第一篇:我们认为通过了解JavaScript构建块以及它们是如何工作,将能够编写更好代码和应用程序。...调用栈是一种数据结构,它记录了我们在程序中位置。如果我们运行到一个函数,它就会将其放置到栈顶,当从这个函数返回时候,就会将这个函数从栈顶弹出,这就是调用栈做事情。...这能清楚知道当异常发生时候堆栈追踪是怎么被构造堆栈状态是如何,让我们看一下下面的代码: image.png 如果这发生在 Chrome 里(假设这段代码实在一个名为 foo.js 文件中)...因此,在执行每一步中,相同函数都会被一次又一次地添加到调用堆栈中,如下所示: image.png 然而,在某些时候,调用堆栈函数调用数量超过了调用堆栈实际大小,浏览器决定采取行动,抛出一个错误...但是在一个线程上运行也非常有限制,由于 JavaScript 只有一个调用堆栈,当某段代码运行变慢时会发生什么? 并发与事件循环 当调用堆栈函数调用需要花费大量时间来处理时会发生什么情况?

    1.1K50

    二进制逆向学习笔记:堆栈图解析汇编中函数调用过程

    C语言中函数 三个关键点:局部变量、参数、函数返回值 下面是示例程序: #include "stdafx.h" int Plus(int x, int y) { int z = 2...: esp:栈顶 ebp:栈底 对于函数调用,先压入参数,再执行call 对于参数,从右向左依次压入堆栈(stdcall模式) 因此,本程式先压入4,再压入3 1.调用堆栈 ?...3. call指令 一般mov等指令无法改变eip值,但是call可以call 00401005: a.将eip值改为函数所在地址0x00401005 b.将函数ret address...4.进入函数后,保留现场,划分堆栈 ? 5.PUSH EBP ? 保留原栈底位置 6.提升堆栈,创建缓冲区 ? 紫色部分即为缓冲区 ?...EAX存放函数返回值 10.恢复堆栈 MOV ESP,EBP ? POP EBP 恢复栈底 ? 11.ret指令 将堆栈函数返回地址pop到eip中 ? ADD ESP,8 平衡堆栈 ?

    1.3K30

    linux网络编程系列(三)--tcp和udp基本函数调用过程如何选择

    通常是计算sizeof(struct sockaddr); myaddr为结构体指针变量 对于不同socket domain定义了一个通用数据结构: //此结构体不常用 struct sockaddr...{ unsigned short int sa_family; //调用socket()时domain参数,即AF_INET值。...,若含有,则调用带MSGOOB标志recv来读取带外数据 原型:int sockatmark(int sockfd); 参数:fd为前面的sfd,newfd 返回值:返回1则说明下一个数据时带外数据,...注意:socket编程还提供了一对函数sendmsg/recvmsg用于读写数据,该对函数既可用于tcp报文,也可用于udp报文,是通用。...协议选择 对数据要求高可靠性应用需选择TCP协议,如验证、密码字段传送都是不允许出错,而对数据可靠性要求不那么高应用可选择UDP传送; TCP协议在传送过程中要使用三次握手、重传确认等手段来保证数据传输可靠性

    94420

    CC++ 反汇编:关于函数调用约定

    函数是任何一门高级语言中必须要存在,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想精髓,今天我将带大家一起来探索函数实现机理,探索编译器到底是如何函数这个关键字进行实现,并使用汇编语言模拟实现函数编程中参数传递调用规范等...一般编译器实现调用调用约定无外乎以下这几种: CDECL:C/C++默认调用约定,调用方平栈,不定参数函数可以使用,参数通过堆栈传递....不同两次函数调用,所形成栈帧也不相同,当由一个函数进入另一个函数时,就会针对调用函数开辟出其所需栈空间,形成此函数独有栈帧,而当调用结束时,则清除掉它所使用栈空间,关闭栈帧,该过程通俗讲叫做栈平衡...对于32位来说使用ecx,edx传递前两个参数,后面的用堆栈传递。 对于64位则会使用RCX,RDX,R8,R9传递前四个参数,后面的用堆栈传递。...但每次访问都需要计算,如果在函数执行过程中esp发生了变化,再次访问变量就需要重新计算偏移了。 参考文献:《C++反汇编与逆向分析技术揭秘》

    62810

    数据结构+算法(第08篇):史上最猛之递归屠龙奥义

    递归调用/重入 = 函数调用 = 堆栈利用 递归实现载体是函数。 计算机利用堆栈来实现函数调用。...具体过程简化如下: 第一步:将参数压入堆栈 第二步:将返回地址压入堆栈 第三步:保存上次函数调用栈帧位置 第四步:执行函数体内业务逻辑 第五步:恢复上次函数调用栈帧位置 第六步:将返回地址从堆栈中弹出...递归调用也好、递归重入也好,说白了都是函数调用。递归重入展开,对计算机系统(编译器+运行时环境)而言,就是针对同一递归函数,不断重复上述过程,直到递归展开结束。 5....如果递归实现体中有多个子递归调用,那么当递归函数返回时,若不清楚返回地址的话,则你会不知道到底是从哪个子递归返回。所以返回地址在这里非常重要。 那么如何得到返回地址呢?...这就有效避免了左递归展开第2步和第4步。 那么在其中子递归调用结束后,如何跳到和它是并列关系另一个子递归继续执行呢?也就是上图中黄色连线效果是如何实现呢?

    65430

    本立道生,Go interface背后对象模型

    毕竟久经C和C++蹂躏,学习新语法,再用它来写代码可谓驾轻就熟。但有几个问题一直困扰着我:类型断言和反射到底是如何实现?interface value到底包含了什么?...我们来思考三个问题: 接口值到底是什么?它是指针吗?如果是的话,指针所指向那块内存内容是什么? any.(Stringer)这样类型断言到底是如何实现? 反射所依赖底层数据结构到底是什么?...如果你了解CPU所支持函数调用过程,同时也在下意识里认同C语言函数调用方式是高级语言函数调用范式的话,就会很想知道下面几个问题答案: s.String()是如何定位到不同String()函数实现...在func (i Binary) String() 这个函数里,类似uint64(i) (将i.Get()展开来)这样对i引用,到底是如何知道i内存地址?...是的,这两个问题也是支持多态(动态分发)语言需要回答问题,对于C++,我们知道它是借助于虚函数表及this指针来实现

    35230

    从创建进程到进入main函数,发生了什么?

    前几天,读者群里有小伙伴提问:从进程创建后,到底是怎么进入我写main函数? 今天这篇文章就来聊聊这个话题。...首先先划定一下这个问题讨论范围:C/C++语言 这篇文章主要讨论是操作系统层面上对于进程、线程创建初始化等行为,而像Python、Java等基于解释器、虚拟机语言,如何进入到main函数执行,这背后路径则更长...所以这里就重点关注C/C++这类native语言main函数如何进入。 ? 本文会兼顾叙述Linux和Windows两个主要平台上详细流程。 创建进程 第一步,创建进程。...其实,在进入main函数之前,还有一个重要工作要做,这就是:C/C++运行时库初始化。上面的 __libc_start_main 就是在完成这一工作。...线程从这里启动后,再通过Windows异步过程调用APC机制执行提前插入APC,进而将执行流程引入应用层,去执行Windows进程应用程序初始化工作,比如一些核心DLL文件加载(Kernel32

    1.4K30

    详解CC++堆栈工作机制

    我们知道,局部变量是存储在堆栈;debug时,查看堆栈可以知道函数调用顺序;函数调用时传递参数,事实上是把参数压入堆栈,听起来,堆栈象一个大杂烩。那么,堆栈(Stack)到底是如何工作呢?...本文将详解C/C++堆栈工作机制。阅读时请注意以下几点: 本文讨论编译环境是 Visual C/C++,由于高级语言堆栈工作机制大致相同,因此对其他编译环境或高级语言如C#也有意义。...之所以引入这个概念,是因为一个函数建立和清理,有些工作是由Caller完成,有些则是由Callee完成。 开始讨论堆栈如何工作 我们来讨论堆栈工作机制。...函数用EBP寄存器来访问参数和局部变量。我们知道,参数地址总是比EBP值高,而局部变量地址总是比EBP值低。而在特定堆栈帧中,每个参数或局部变量相对于EBP地址偏移总是固定。...堆栈清理顺序和堆栈建立顺序刚好相反(堆栈销毁过程就不一一画图说明了): 1)如果有对象存储在堆栈帧中,对象析构函数会被函数调用

    48320

    C语言 | C++ 堆栈工作机制

    那么,堆栈 (Stack) 到底是如何工作呢?本文将详解 C/C++ 堆栈工作机制。...阅读时请注意以下几点: 1)本文讨论编译环境是 Visual C/C++,由于高级语言堆栈工作机制大致相同,因此对其他编译环境或高级语言如 C# 也有意义。...之所以引入这个概念,是因为一个函数建立和清理,有些工作是由 Caller 完成,有些则是由 Callee 完成。 开始讨论堆栈如何工作 我们来讨论堆栈工作机制。...而在特定堆栈帧中,每个参数或局部变量相对于 EBP 地址偏移总是固定。因此函数对参数和局部变量访问是通过 EBP 加上某个偏移量来访问。...堆栈清理顺序和堆栈建立顺序刚好相反:(堆栈销毁过程就不一一画图说明了)     1)如果有对象存储在堆栈帧中,对象析构函数会被函数调用

    7.8K88

    堆栈与堆(Stack vs Heap):有什么区别?一组图片给你讲清楚!

    在下面的解释中,我们将介绍运行每行重要代码后堆和堆栈如何变化。尽管我们用C++,但对 Python 和 Java 解释也同样适用。我们在这里只讨论堆栈段。...有限可访问性:请务必记住,存储在堆栈内存中数据只能在活动函数调用期间访问。 自动管理:堆栈内存高效管理由系统本身完成,不需要我们额外工作。...注意:在 Java 和 Python 中,垃圾收集会自动处理内存释放,无需手动释放内存,如 C++ 中所示。 在下面的解释中,我们将讨论运行每行重要代码后堆和堆栈如何变化。...显示result值后),栈段和堆段再次清空 7共7 个 以下是 C++ 代码按执行顺序解释: 第 3 行:main调用函数,并为其创建一个新堆栈帧。...ptr 注意:C++ 标准库还提供了一系列智能指针,可以帮助自动化堆中内存分配和释放过程

    1.7K10

    C语言内联函数,提升C技巧必备

    第一时间看干货文章 1 内联函数是C语言从C++中借鉴过来,适当使用内联函数可以提高程序执行效率。本篇文章就来讲解下内联函数,赶紧来看下吧!...现代计算机系统做法都是会在执行函数B之前,先把R0寄存器值保存到堆栈中,函数B执行结束后,再将堆栈值恢复到R0寄存器中,然后函数A继续执行,这样对于数据处理就不会有任何问题了。...(可以与宏函数做类比),在调用处将代码展开,相当于自动将函数B代码在调用地方复制了一份副本,没有了保护现场和恢复现场时间,从而节省了函数调用开销。...1:2; return 0; } 内联函数调用展开了。...编译过程中,宏调用并不执行类型检查,甚至连正常参数也不检查,内联函数虽然具有宏展开特性,但其本质仍是函数,编译器仍可以对其进行参数检查,而宏就不具备这个功能。

    62030

    C++函数——内联函数&函数指针

    而这个过程是在代码编译过程即完成,当我们将一个函数定义为内联函数时,编译器识别到内联函数特征后,就将函数定义替换到函数调用。那么我们怎么定义内联函数呢?...为什么要用内联函数 我们在代码中经常会用到一些小函数,它们逻辑简单,代码量少,但是如果考虑到这些函数调用调用时候,我们会发现大部分时间都耗费在调用这个过程,也就是程序从主函数跳转到被调用函数过程...因此,对于内联函数,编译器不必跳到另一个位置去执行函数,然后再跳回去,因为被调用程序代码已经是调用程序中代码一部分了。...下面我们列举一下内联函数优缺点: 优点: 1、内联函数通过避免函数调用开销从而加速了我们程序 2、当函数调用发生时,内联函数节省了堆栈上变量push/pop开销 3、内联函数节省了从函数返回调用开销...对于函数指针与内联函数说明这篇文章就到这里,由于是基础系列文章,先不详细展开,还有一些知识需要用实例和练习加以说明。以后如果出高级系列再详细展开讨论。

    2.5K21

    认真理一理C++构造函数

    如何使用构造函数 什么是委托构造函数如何禁止拷贝形式初始化? 前言 我们在C语言中使用堆栈变量时,常常需要给它赋初始值,用于避免使用到了不可预知值。...同样,在C++中也需要有这样动作,只是由于C++对象可能比基本数据要复杂得多,因此使用了一系列函数来完成这件事。这些函数就是构造函数。那么构造函数到底是怎样,又该如何使用呢?...在《C++类初识》中已有所介绍,这里再稍微展开一下。...C++11中提供委托构造函数说白了就是构造函数使用其他定义好构造函数执行自己初始化过程。...总结 关于构造函数内容还有很多,在介绍继承,多态,拷贝,移动等内容后再展开,本文总结如下: 构造函数没有返回值 构造函数名与类名相同 构造函数可以重载 构造函数不能被声明成const 对于只有一个实参构造函数而言

    55820

    Linux下跨语言调用C++实践

    该部分涉及到参数类型映射,以及如何函数中传递struct、指针等高级类型,可以参考附录中文档。...4.2 跨语言调用如何实现参数传递 C/C++函数调用标准过程如下: 在内存栈空间中为被调函数分配一个栈帧,用来存放被调函数形参、局部变量和返回地址。...由于Python/Java调用过程基本一致,我们以Java调用过程为例来进行解释,对于Python调用过程不再赘述。...,但是经过上述分析也不难发现,在一次跨语言本地化调用过程中,仍然有大量跨语言工作需要完成,这些过程也需要支出对应算力。...而跨语言调用开销,主要包括三部分: 对于JNA这种由动态代理实现跨语言调用,在调用过程中存在堆栈切换、代理路由等工作

    5.9K40

    C++ 特性使用建议

    但是缺省参数函数调用代码难以呈现所有参数,开发者只能通过查看函数申明或定义确定如何使用API,当缺省参数不适用于新代码时可能导致重大问题。...变长数组和 alloca() 不是标准 C++ 组成部分,更重要是,它们根据数据大小动态分配堆栈内存,会引起难以发现内存越界 bugs。...(4)不要试图使用展开后会导致 C++ 构造不稳定宏,不然也至少要附上文档说明其行为。 (5)不要用 ## 处理函数,类和变量名字。...对于空指针,到底是用 0,NULL 还是 nullptr,C++11 项目用 nullptr,C++03 项目则用 NULL,不要使用0来表示空指针,毕竟 NULL 和 nullptr 看起来更像指针。...考虑一下你们团队成员平均水平是否能够读懂并且能够维护你写模板代码。或者一个非C++ 程序员和一些只是在出错时候偶尔看一下代码的人能够读懂这些错误信息或者能够跟踪函数调用流程。

    1.7K20

    EmmyLua MobDebug浅析

    stack()函数: 上面介绍过stack指令最后就会调用到这个函数, 函数本身实现也比较简单, 枚举每一层call stack并记录相应stack基本信息, local变量列表, upvalue...断点相关操作函数: 环境表提取函数 capture_vars() 这是mobdebug中很重要一个函数, 如前面介绍exec指令, 或者说当我们在某层Stack上展开本地变量时候...getfenv(), 在lua5.2+版本该函数已经取消, 有兴趣可以自行查看mobdebug.lua, 看5.2+中getfenv()是如何实现)....工作流程, 也就是我们调用start()开启debug session后IDE与目标调试应用程序之间交互过程, 我们简单过一下以上每个步骤: 1....应用程序返回获取到堆栈结果到IDE, 过程中就会用到上面介绍stack()函数以及序列化相关函数, 最后结果以字符串方式通过指令表中返回结果格式发回到IDE(此时我们发现我们已经可以在IDE

    1.3K20

    垃圾回收机制与无锁化编程(Garbage Collection and Lock-Free Programming)

    先看下C++CAS函数调用: bool __sync_bool_compare_and_swap( type *ptr, type oldval, type newval, ...); type...C++CAS函数调用可以保证对ptr指向变量修改是原子,要么更改完成,要么不做更改。 再看下硬件提供原子操作。...编程语言编译器在X86架构下编译时,会负责把CAS库函数调用编译成基于cmpxchg机器代码。...比如C++编译器GCC在编译时如果碰到上面两个CAS函数调用,会生成包含cmpxchg指令目标码。...无锁化编程示例:无锁化堆栈C++实现 上面用Java实现无锁化堆栈,还是比较简单,几十行代码就完成了。那用C++来实现无锁化堆栈会不会也很简单呢?

    80910

    小朋友学C++(20):内联函数

    在大多数机器上,调用函数都要做很多工作调用前要先保存寄存器,并在返回时恢复,复制实参,程序还必须转向一个新位置执行 C++中支持内联函数,其目的是为了提高函数执行效率,用关键字 inline 放在函数定义...(注意是定义而非声明)前面即可将函数指定为内联函数,内联函数通常就是将它在程序中每个调用点上“内联地”展开,假设我们将 max 定义为内联函数,即上面第(3)种方式,那么若调用代码为 cout <...当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常函数调用机制进行调用. 优点: 当函数体比较小时候, 内联该函数可以令目标代码更加高效....对于存取函数以及其它函数体比较短, 性能关键函数, 鼓励使用内联. 缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数大小....(递归调用堆栈展开并不像循环那么简单, 比如递归层数在编译时可能是未知, 大多数编译器都不支持内联递归函数)。

    37620
    领券