什么是堆栈不平衡?

Fra*_*ter 2 stack f# memory-management terminology

阅读这篇文章F#Versus数学:第一部分 - BLAS和LAPACK入门我偶然发现stack imbalance了段落中的术语A Warning, Perhaps an Omen.

用Google搜索和搜索上的SO,但只能找到人栈的不平衡和不generall解释挣扎.

奖金问题: 它只影响f#还是C,C++,Python,Java等中的一般问题?

如有必要,请更改问题的标签

mek*_*ian 9

当用于跟踪被调用函数,参数和返回值的数据结构变得损坏或未对齐时,会发生堆栈不平衡.

大多数情况下,堆栈是一个内存指针,用于存储当前函数调用退出回调用者时控件将恢复的地址.这有不同的变体,有时函数的参数也会附加到堆栈,以及返回值.这里最重要的是调用者和被调用者应该同意如何在被调用者退出时将其恢复到先前状态.该协议通常称为" 呼叫公约".

在.NET中,堆栈不平衡是纯托管代码中难得存在的问题.但是,在调用非托管代码时,这可能是一个常见的问题,因为您需要告诉编译器应该如何调用该方法,这意味着应该如何根据调用约定清理堆栈.

在Windows上,有一些标准调用约定涵盖了大量的调用案例.

stdcall - Callee将在退出时修复堆栈.
fastcall - 除了返回地址之外,可能不需要修复堆栈,而是使用CPU寄存器来传递参数.
cdecl - 调用者将在被调用函数返回后修复堆栈.

这里有一个正式的参考:MSDN的参数传递和命名约定

这也是有趣的:X86调用约定列表@维基百科

在给定的开发域中,这往往不是问题.每种语言通常都有一个隐含在所有方法调用中的约定.C/C++使用相同的约定来调用C/C++调用,Python用于其他Python调用等.当跨域时,如果一个域不使用相同的域,它可能会成为一个问题.也许在Windows中最常见的是,使用"C"样式声明(cdecl)导出的函数可能会在调用时导致不平衡堆栈(或更糟糕),就好像它有一个stdcall约定,这是WINAPI(windows系统)调用识别的方法.


jgl*_*uie 5

前几天我们刚刚看到了这一点(使用C#和C ++编组)

我请您参考MSDN页面上的文字:

如果在DllImportAttribute属性中指定了调用约定以及在DllImportAttribute属性中指定了调用约定,则当CLR检测到平台调用调用后的堆栈深度与预期的堆栈深度不匹配时,将激活pInvokeStackImbalance管理的调试助手(MDA)。托管签名。

我意识到这是针对特定的编译器警告的,但是该页面提供了一些信息,说明什么是堆栈不平衡,是什么原因引起的,是什么症状以及如何解决它。正如Daniel所说,这通常是由于托管和非托管签名不匹配所致。

希望这可以帮助。