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

在CDECL调用约定中,我可以重用推送到堆栈上的参数吗?

在CDECL调用约定中,参数是通过堆栈进行传递的。根据CDECL调用约定的规定,函数的调用者负责清理堆栈上的参数。因此,在CDECL调用约定中,不能重用推送到堆栈上的参数。

CDECL调用约定是一种常见的函数调用约定,特点是参数从右向左依次推送到堆栈上,函数返回时由调用者负责清理堆栈。这种调用约定通常用于C和C++语言中的函数调用。

由于参数是通过堆栈传递的,函数在使用参数时会直接从堆栈上读取。如果尝试重用推送到堆栈上的参数,可能会导致函数读取到错误的值,从而产生不可预测的结果。

总结起来,在CDECL调用约定中,不建议重用推送到堆栈上的参数。应该确保每次函数调用时,提供新的参数值以避免潜在的错误。

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

相关·内容

ndk C++ 编译器函数名修饰规则

1、__stdcall调用约定:函数参数自右向左通过栈传递,被调用函数返回前清理传送参数内存栈, 2、_cdecl是C和C++程序缺省调用方式。...3、__fastcall调用约定:它是通过寄存器来传送参数(实际,它用ECX和EDX传送前两个双字(DWORD)或更小参数,剩下参数仍旧自右向左压栈传送,被调用函数返回前清理传送参数内存栈...MakeFun函数认为是 __cdecl调用方式,b模块这些函数调用完MakeFun当然要帮着恢复堆栈啦,可是MakeFun已经结束时自己恢复了堆栈,b模块函 数这样多此一举就引起了栈指针错误...参数传递,有两个很重要问题必须得到明确说明: 当参数个数多于一个时,按照什么顺序把参数压入堆栈 函数调用后,由谁来把堆栈恢复原状 高级语言中,通过函数调用约定来说明这两个问题。...其中函数开始处保留esp到ebp函数结束恢复是编译器常用方法。 从函数调用看,2和1依次被push进堆栈,而在函数又通过相对于ebp(即刚进函数时堆栈指针)偏移量存取参数

2K31

请教关于C语言形参和实参存储单元问题?

除了cdecl以外,C其他常用调用约定包括stdcall和fastcall,C++还有一个thiscall(用于调用成员函数)。fastcall会使用寄存器来传递一部分参数。...stdcall除了返回时自动清理堆栈以外,与cdecl使用参数上区别不大。thiscall调用约定使用寄存器传递this指针参数。...pascal调用约定跟stdcall类似,但是参数入栈顺序是反cdecl调用约定下,所有参数从右往左入栈,都要占用存储空间。...是x86调用约定,x64已经不同了,查了一下相关资料,Windows和非Windows,使用调用约定是有差异。...另外,调用栈上额外分配32个字节(但是不需要初始化),给RCX、RDX、R8、R9四个参数,这样被调用函数需要使用这四个寄存器时候可以把这四个参数直接存到堆栈里对应位置,腾出寄存器空间。

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

    函数是任何一门高级语言中必须要存在,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想精髓,今天将带大家一起来探索函数实现机理,探索编译器到底是如何对函数这个关键字进行实现,并使用汇编语言模拟实现函数编程参数传递调用规范等...一般编译器实现调用调用约定无外乎以下这几种: CDECL:C/C++默认调用约定调用方平栈,不定参数函数可以使用,参数通过堆栈传递....cdecl 调用者平栈: cdecl是C/C++默认调用约定,该调用方式函数内不进行任何平衡参数操作,而是退出函数后对esp执行加4操作,从而实现栈平衡。...stdcall 被调用者平栈: stdcall与cdecl参数平衡上有所不同,其余部分都一样,但该约定不定参数函数无法使用。...cdecl调用方式函数同一作用域内多次被调用,会在效率比stdcall高一些,因为它可以使用复写传播优化,而stdcall函数内平衡栈,无法使用复写传播优化。

    62810

    5.5 汇编语言:函数调用约定

    一般情况下在Win32环境默认遵循就是STDCALL,而在Win64环境下使用则是FastCALL,Linux系统则遵循SystemV约定,这里整理了他们之间异同点....CDECL:C/C++默认调用约定调用方平栈,不定参数函数可以使用,参数通过堆栈传递. STDCALL:被调方平栈,不定参数函数无法使用,参数默认全部通过堆栈传递....STDCALL是一种被调用者平栈约定,这意味着,函数调用过程,被调用函数使用栈来存储传递参数,并在函数返回之前移除这些参数,这种方式可以使调用代码更短小简洁。...通过以上分析发现_cdecl与_stdcall两者只参数平衡上有所不同,其余部分都一样,但经过优化后_cdecl调用方式函数同一作用域内多次使用,会在效率比_stdcall髙,这是因为_cdecl...它通常采用被调用者平衡堆栈方式,类似于STDCALL调用约定。但是,FASTCALL约定规定函数前两个参数ECX和EDX寄存器传递,节省了压入堆栈所需指令。

    26520

    2020-09-04:函数调用约定了解么?

    __cdecl 在被调用函数 (Callee) 返回后,由调用方 (Caller) 调整堆栈。 函数实参在线程栈按照从右至左顺序依次压栈。...实际__fastcall用ECX和EDX传送前两个DWORD或更小参数,剩下参数仍自右向左压栈传送,被调用函数返回前清理传送参数内存栈。...__pascal 基于Pascal语言调用约定参数从左至右入栈(与cdecl相反)。被调用者负责返回前清理堆栈。...要求尽可能在寄存器传递参数。函数名改编为”@@函数名@参数字节数十进制”。这是微软自己添加标准。 8.syscall 与cdecl类似,参数被从右到左推入堆栈。...从最左边开始三个字符变元会被放置EAX, EDX和ECX,最多四个浮点变元会被传入ST(0)到ST(3)----虽然这四个参数空间也会在参数列表保留。

    59910

    5.5 汇编语言:函数调用约定

    一般情况下在Win32环境默认遵循就是STDCALL,而在Win64环境下使用则是FastCALL,Linux系统则遵循SystemV约定,这里整理了他们之间异同点.CDECL:C/C++...默认调用约定调用方平栈,不定参数函数可以使用,参数通过堆栈传递.STDCALL:被调方平栈,不定参数函数无法使用,参数默认全部通过堆栈传递.FASTCALL32:被调方平栈,不定参数函数无法使用...STDCALL是一种被调用者平栈约定,这意味着,函数调用过程,被调用函数使用栈来存储传递参数,并在函数返回之前移除这些参数,这种方式可以使调用代码更短小简洁。...通过以上分析发现_cdecl与_stdcall两者只参数平衡上有所不同,其余部分都一样,但经过优化后_cdecl调用方式函数同一作用域内多次使用,会在效率比_stdcall髙,这是因为_cdecl...它通常采用被调用者平衡堆栈方式,类似于STDCALL调用约定。但是,FASTCALL约定规定函数前两个参数ECX和EDX寄存器传递,节省了压入堆栈所需指令。

    32420

    C语言函数调用约定

    函数调用惯例函数声明和函数定义时都可以指定,语法格式为: ‌返回值类型 调用惯例 函数名(函数参数) int __cdecl max(int m, int n); // __cdecl是C语言默认调用约定...,平时编程,我们并没有去指定调用约定,就使用默认 __cdecl。...除了 cdecl,还有其他调用约定调用约定 参数传递方式 参数出栈方式 名字修饰(编译器重命名函数) cdecl 从右到左顺序入栈 调用方(caller) _+...但是 __cdecl 调用方式是由函数调用者负责清除栈函数参数,所以这种方式支持可变参数,比如 printf()和 Windows API wsprintf()就是 __cdecl调用方式。...调用者负责分配32字节“shadow space”,用于存放那四个存放调用参数寄存器值(亦即前四个调用参数);小于64位(bit)参数传递时高位并不填充零(例如只传递ecx),大于64位需要按照地址传递

    17910

    关于this指针

    几种常用调用约定: 其中,_cdecl是C/C++默认调用约定,VC调用约定并没有_thiscall这个关键字,它是类成员函数默认调用约定; C/C++main函数调用约定必须是_...对于_cdecl调用约定,为什么是调用者而不是函数体自己来平衡堆栈呢?...,所以我们调用者来进行堆栈平衡操作。...这里我们重点说一下_thiscall调用约定: 它只能用在类成员函数上 参数从右向左进行压栈 若参数个数确定,this指针通过ecx寄存器传递给被调用者;若参数不确定,this指针在所有参数被压栈后压入堆栈...对于参数不确定函数,调用者清理堆栈,否则函数自己清理堆栈。 问题:this指针是否可以为空?

    42910

    linux 编译 c或cpp 文件为动态库 so 文件(最简单直观模板)

    这些堆栈参数由被调用函数返回后清除,使用指令是 retnX,X表示参数占用字节数,CPUret之后自动弹出X个字节堆栈空间。称为自动清栈。...C不加说明默认函数为_cdecl方式(C也只能用这种方式),C++也一样,但是默认调用方式可以IDE环境设置。...1、__stdcall调用约定:函数参数自右向左通过栈传递,被调用函数返回前清理传送参数内存栈。 2、__cdecl是C和C++程序缺省调用方式。...每一个调用函数都包含清空堆栈代码,所以产生可执行文件大小会比调用_stdcall函数大。函数采用从右到左压栈方式。注意:对于可变参数成员函数,始终使用__cdecl转换方式。...3、__fastcall调用约定:它是通过寄存器来传送参数(实际,它用ECX和EDX传送前两个双字(DWORD)或更小参数,剩下参数仍旧自右向左压栈传送,被调用函数返回前清理传送参数内存栈

    5.7K40

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

    我们知道,局部变量是存储堆栈;debug 时,查看堆栈可以知道函数调用顺序;函数调用时传递参数,事实是把参数压入堆栈,听起来,堆栈象一个大杂烩。...个字节)如下图所示: 图6 还不知道编译器为什么这么设计,或许是为了堆栈插入调试数据,不过这无碍我们今天讨论。...返回值是如何传递 堆栈帧建立起后,函数代码真正地开始执行,它会操作堆栈参数,操作堆栈局部变量,甚至堆(Heap)创建对象,balabala…....有 2 个办法可以指定函数使用调用约定: 1)函数定义时加上修饰符来指定,如 void __thiscall mymethod();{ ...} 2) VS 工程设置为工程定义所有的函数指定默认调用约定...常用调用约定有以下3种: 1)__cdecl。这是 VC 编译器默认调用约定。其规则是:参数从右向左压入堆栈,函数退出时由 caller 清理堆栈参数

    7.8K88

    详解CC++堆栈工作机制

    我们知道,局部变量是存储堆栈;debug时,查看堆栈可以知道函数调用顺序;函数调用时传递参数,事实是把参数压入堆栈,听起来,堆栈象一个大杂烩。那么,堆栈(Stack)到底是如何工作呢?...堆栈特性分析 一节,一个完整堆栈帧已经建立起来,现在函数可以开始正式执行代码了。本节我们对堆栈特性进行分析,有助于了解函数与堆栈依赖关系。 1....返回值是如何传递 堆栈帧建立起后,函数代码真正地开始执行,它会操作堆栈参数,操作堆栈局部变量,甚至堆(Heap)创建对象,balabala…....有2个办法可以指定函数使用调用约定: 1)函数定义时加上修饰符来指定,如: void __thiscall mymethod(); { ... } 2)VS工程设置为工程定义所有的函数指定默认调用约定...常用调用约定有以下3种: 1)__cdecl。这是VC编译器默认调用约定。其规则是:参数从右向左压入堆栈,函数退出时由caller清理堆栈参数

    48320

    关于函数参数入栈思考(函数调用约定,入栈顺序)

    向被调函数传递参数可以有不同方式实现。这些方式被称为“调用规范”或“调用约定”。C/C++中常见调用规范有__cdecl、__stdcall、__fastcall和__thiscall。...__cdecl调用约定 又称为C调用约定,是C/C++默认函数调用约定,它定义语法是: int function (int a ,int b) // 不加修饰就是C调用约定...int __cdecl function(int a,int b) // 明确指出C调用约定 约定内容有: (1)参数入栈顺序是从右向左; (2)在被调用函数 (Callee) 返回后...__stdcall调用约定 又称为标准调用约定,申明语法是: int __stdcall function(int a,int b) 约定内容有: (1)参数从右向左压入堆栈; (2...this指针在所有参数压栈后被压入堆栈; (3)对参数个数不定调用者清理堆栈,否则函数自己清理堆栈

    2.6K31

    进入编译器后,一个函数经历了什么?

    函数调用约定 工作人员拿到了资料,瞅了几眼,问到:“请问你调用约定是什么?” 有些懵,不太懂他意思,小声问到:“不好意思,你刚问什么?”...工作人员有点不耐烦了,提高了音量,“是问你调用约定是什么?调用约定啊!” 看见我仍然一脸茫然,工作人员直接给我资料上调用约定那一栏盖上了一个标记:cdecl。...有点摸不着头脑,同行小伙伴str_lower拽了一下说到:“他是问你函数调用约定,就是约定调用函数方式,涉及怎么传递参数,谁来恢复调用栈等” 他这一说才反映过来,“这个调用约定都有哪些可选呢...,小声问到。 工作人员没有搭理我,忙着给我资料加东西。 旁边小伙伴又把拽了过去,说到:“咱们函数里面定义局部变量、参数是存放在线程栈里面的。...线程要不断游走在不同函数调用函数后为了能回到原来地方,调用之前把返回地址也放在了线程栈里。就像这样,你看会不会有什么问题:” ?

    74210

    函数调用约定

    本篇原创作者:Rj45 背景 在前面的文章可以发现无论是x86架构还是x64架构程序,其内部函数在被调用时候, 都是首先将函数参数压入栈(而且是从右向左),然后调用函数,最后还需要调整栈帧。...(x64架构程序使用寄存器传参时候无需调整栈帧) 这种将函数参数顺序压入栈以及进行栈帧调整现象叫做函数调用约定。...函数调用约定 1、类型 函数调用约定有三种类型,分别为: __cdecl __stdcall __fastcall 2、区别 _cdecl:是C或C++默认函数调用方式,函数参数从右向左入栈,主调函数负责栈平衡...__fastcall:是一种快速调用方式,将参数优先从寄存器传入ecx和edx,剩下参数再从右向左入栈,被调用函数恢复栈顶指针。 栈平衡 栈平衡,也叫esp定律或者堆栈平衡。...其意思是,向堆栈压入下一行程序地址,当在进入子程序后进行反向运动时候,可以恢复到原程执行下一条指令地址位置。

    1.9K50

    大神洗礼第四讲——函数相关及编程技巧

    2、 Call Convention(函数调用约定) 、_cdecl a、 参数从右向左压入堆栈 b、 函数被调用者修改堆栈 c、 win32应用程序里,宏APIENTRY,WINAPI,...每一个调用函数都包含清空堆栈代码,所以产生可执行文件大小会比调用_stdcall函数大。...、_stdcall a、 压栈方式与_cdecl一样,与之不一样堆栈平衡不是由函数调用者完成,而是自身完成,退出时自己清空堆栈。...esp,ebp 31 013116CE pop ebp 32 013116CF ret 33 34 00D21D88 push 2 ;调用函数之前先将参数从右往左压入堆栈...n", MyFunc()); 2012110222341843.png 练习: 、无参数情况(不在堆栈展开) 1 void _declspec (naked) BlankFunc(void

    652100

    调用约定

    使用IDAF5功能时经常能够看到函数签名带有cdecl、fastcall等字样,这些就是调用约定调用约定是通常是特定于语言、编译器和CPU,这里只简单了解一下主流调用约定。...C调用约定cdecl)   x86体系结构许多C编译器使用默认调用约定叫做C调用约定cdecl)。...,如printf 要求调用方从栈删除参数好处: 可变参数函数调用时,调用方清楚知道传入参数数量,因此能够轻松做出调整,而被调用方无法事先知道自己会收到多少个参数。...stdcall规定: 调用方将所需参数放入栈 参数放入顺序为从右往左 调用结束后由被调用方清楚参数 要求被调用方从栈删除参数特点: 被调用方要完成清除参数任务,必须清楚知道栈中有多少个参数,只有函数参数数量固定不变时才有可能...fastcall规定: 能够将最多两个参数存放在寄存器 传递给函数前两个参数将分别位于ECX和EDX寄存器 剩余参数以类似于stdcall约定方式从右往左放入栈 C++调用约定(thiscall

    85840

    函数调用堆栈变化情况

    函数一般要利用参数,而且内部也会用到局部变量,在对表达式进行求值时,编译器还会生成一些无名临时对象,这些对象都是存放在堆栈。 下面以Visual C++编译器为例进行研究,考察如下程序。...环境下,以C/C++默认函数调用约定__cdecl来生成该程序调试版本(Debug)汇编代码。...,结束函数 注意:以上汇编代码对mixAdd()函数调用采用函数调用约定是__cdecl,这是C/C++程序默认函数调用约定,其重要一点就是在被调用函数 (Callee) 返回后,由调用方 (Caller...)调整堆栈,因此main()函数调用mixAdd()地方会出现add esp 8这条指令。...有关函数调用约定介绍见我另一篇blog:关于函数参数入栈思考。

    76310

    堆和栈区别

    2.5堆和栈存储内容  栈: 函数调用时,第一个进栈是主函数下一条指令(函数调用语句下一条可执行语句)地址,然后是函数各个参数大多数C编译器参数是由右往左入栈,然后是函数局部变量...对于一个进程内存空间而言,可以逻辑分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。...我们可以先了解一下函数调用过程,以便对堆栈程序作用有更深入了解。不同语言有不同函数调用规定,这些因素有参数压入规则和堆栈平衡。...BTW,Windows系统API函数基本是__stdcall调用形式,只有一个API例外,那就是wsprintf,它使用__cdecl调用规则,同printf函数一样,这是由于它参数个数是可变缘故...这能够减少对进程堆(或全局堆)分配/释放调用次数,也允许最大限度重用曾经分配块。另外,分配高速缓存允许收集统计信息,以便较好地理解对象较高层次使用。

    1.3K90

    CC++ 反汇编:函数与结构体

    当有参函数被执行时,通常会根据不同调用约定来对参数进行压栈存储 以STDcall约定为例,栈调用原则是先进后出,最先被push到堆栈数据会被最后释放出来,而CPU中有两个寄存器专门用于维护堆栈变化...STDCALL调用约定,一般情况下在Win32环境默认遵循就是STDCALL,而在Win64环境下使用则是FastCALL,Linux系统则遵循SystemV约定,这里整理了他们之间异同点...这里我们来演示CDECL调用约定,其实我们使用Printf()函数就是遵循__cdecl()约定,由于Printf函数可以有多个参数传递,所以只能使用__cdecl()约定来传递参数,该约定典型特点就是平栈不在被调用函数内部完成...与_stdcall两者只参数平衡上有所不同,其余部分都一样,但经过优化后_cdecl调用方式函数同一作用域内多次使用,会在效率比_stdcall髙,这是因为_cdecl可以使用复写传播,而_stdcall...故Windows环境_fastcall调用方式只使用了ECX和EDX寄存器,分别传递第1个参数和第2个参数,其余参数传递则依然使用堆栈传递.

    1.1K40
    领券