切换 C++ 函数的调用堆栈

Posted

技术标签:

【中文标题】切换 C++ 函数的调用堆栈【英文标题】:Switching callstack for C++ functions 【发布时间】:2009-09-03 13:24:04 【问题描述】:

这是我关于切换 C 调用堆栈的previous question。但是,C++ 使用不同的调用约定(thiscall)并且可能需要一些不同的 asm 代码。有人可以解释差异并指出或提供一些切换 C++ 调用堆栈的代码 sn-ps(最好在 GCC 内联 asm 中)吗?

谢谢, 詹姆斯

【问题讨论】:

是否有理由自己滚动而不是使用 setjmp / longjmp? 【参考方案1】:

上一个问题中给出的代码应该可以正常工作。

thiscall calling convention 的区别仅在于谁负责将参数从堆栈中弹出。在 thiscall 调用约定下,被调用者弹出参数(另外,this 指针在 ecx 中传递);在 C 调用约定下,调用者弹出参数。这不会影响上下文切换。

但是,如果您要自己进行上下文切换,请注意,除了切换堆栈之外,您还需要保存和恢复寄存器(可能在堆栈上)。

请注意,顺便说一句,C++ 并不总是使用 thiscall ——它只用于具有固定数量参数的方法(除此之外,它是微软主义...... g++ 不使用它)。

【讨论】:

嗯,这个调用不只是关于隐藏的this参数传递给被调用者的位置吗? (在某些寄存器中,IIRC;但我对此已经超出了我的理解范围,所以如果我在这里语无伦次地喋喋不休,请忽略我......) 您确定没有将 thiscall 与 fastcall 混淆吗?如果我没记错的话,thiscall 是通过 ecx 传递 this 指针的,而编译器有时确实使用 fastcall 来通过寄存器传递参数,而不是将它们推入堆栈。 是的,这听起来很对。我添加了指向 MSDN 条目的链接,其中包含详细信息。【参考方案2】:

注意 C++ 的 ABI 没有明确定义。

这个想法是编译器制造商能够针对这种情况使用最佳调用约定,从而使 C++ 更快。

这样做的缺点是每个编译器都有自己的调用约定,因此来自不同编译器的代码不兼容(即使来自同一编译器的不同版本(甚至不同优化标志)的代码也可能不兼容)。

【讨论】:

以上是关于切换 C++ 函数的调用堆栈的主要内容,如果未能解决你的问题,请参考以下文章

PInvokeStackImbalance C# 调用非托管 C++ 函数

C++ 堆栈分配对象,显式析构函数调用

C++ 堆栈分配的对象赋值和析构函数调用

C++ 函数调用与堆栈上推送/弹出的新块

C++获得程序的调用栈的几种方法

在 C++ 中抛出后会调用析构函数吗?