gpt4 book ai didi

.net - 为什么在违反调用约定的情况下 PInvoke 不会崩溃(在 .NET 3.5 中)?

转载 作者:行者123 更新时间:2023-12-04 22:00:52 24 4
gpt4 key购买 nike

我的解决方案有一个非托管 C++ DLL,它导出一个函数,以及一个 PInvokes 这个函数的托管应用程序。

我刚刚将解决方案从 .NET 3.5 转换为 .NET 4.0 并得到这个 PInvokeStackImbalance “对 PInvoke 函数的调用 [...] 使堆栈不平衡”异常。事实证明,我正在调用 __cdecl'ed 函数,因为它是 __stdcall:

C++ 部分(被调用者):

__declspec(dllexport) double TestFunction(int param1, int param2); // by default is __cdecl

C# 部分(调用者):
[DllImport("TestLib.dll")] // by default is CallingConvention.StdCall
private static extern double TestFunction(int param1, int param2);

所以,我已经修复了这个错误,但现在我对它在 .NET 3.5 中是如何工作的感兴趣?为什么(多次重复)没有人(既不是被调用者,也不是调用者)清理堆栈的情况,没有导致堆栈溢出或其他一些不当行为,但工作正常? PInvoke 中是否有某种检查,就像 Raymond Chen 在他的 article 中提到的那样?
这也很有趣,为什么相反类型的破坏约定(让 __stdcall 被调用者像 __cdecl 一样被 PInvoked)根本不起作用,只导致 EntryPointNotFoundException。

最佳答案

PInvokeStackImbalance也不异常(exception)。这是MDA警告,由托管调试助手实现。使该MDA处于事件状态是可选的,您可以从“调试+异常”对话框中对其进行配置。当您没有调试器运行时,它将永远不会处于事件状态。

使堆栈失衡会导致非常麻烦的问题,从奇怪的数据损坏到获得SOE或AVE。也很难诊断。但这也不会造成任何麻烦,方法返回时将恢复堆栈指针。

编译为64位的代码倾向于具有弹性,更多的函数参数通过寄存器而不是堆栈传递。当被迫在VS2010的新默认值x86上运行时,它将失败。

关于.net - 为什么在违反调用约定的情况下 PInvoke 不会崩溃(在 .NET 3.5 中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5034599/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com