首页 > 后端开发 > C++ > 为什么使用'Cdecl”的 C# P/Invoke 调用在与'__stdcall” C 函数交互时有时会崩溃?

为什么使用'Cdecl”的 C# P/Invoke 调用在与'__stdcall” C 函数交互时有时会崩溃?

Barbara Streisand
发布: 2025-01-25 23:56:11
原创
660 人浏览过

Why Do C# P/Invoke Calls Using `Cdecl` Sometimes Crash When Interfacing with `__stdcall` C   Functions?

了解 P/Invoke 调用约定冲突

如果调用约定不匹配,使用 P/Invoke 从 C# 调用 C 函数可能会导致崩溃。 本文探讨了这些冲突背后的原因。

调用约定不匹配及其影响

常见场景涉及使用 __stdcall 约定的 C 函数,而相应的 C# DllImport 属性指定 CallingConvention.Cdecl。发生这种情况是因为:

  • __stdcall: Windows API 和许多 C 函数的标准调用约定。被调用的函数(callee)负责清理堆栈。 这是 P/Invoke 默认值。
  • __cdecl: 用于 C 代码。调用函数 (caller) 负责堆栈清理。

问题:堆栈不平衡

当调用者和被调用者在堆栈清理方面存在分歧时,就会导致堆栈不平衡。这会导致崩溃、不可预测的行为以及由于丢失堆栈信息而导致的调试不可靠。

其他调用约定(以及它们为何重要)

  • __thiscall: 在 C 中用于成员函数。 由于继承的复杂性和编译器的差异,.NET P/Invoke 不直接支持它。
  • __fastcall: 使用 CPU 寄存器进行参数传递。 托管代码不受支持。
  • __clrcall: 托管代码约定,将 __stdcall__cdecl__fastcall 的各个方面与运行时安全检查相结合。

为什么默认的 P/Invoke 约定会导致问题

默认的 P/Invoke 调用约定 (stdcall) 通常与使用 __cdecl 编译的 C 代码发生冲突。这源于 __stdcall 与 Windows API 的历史关联,导致所有 C 函数都使用它的(错误的)假设。 这种不匹配会导致上述堆栈清理问题。

以上是为什么使用'Cdecl”的 C# P/Invoke 调用在与'__stdcall” C 函数交互时有时会崩溃?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板