ホームページ > バックエンド開発 > C++ > `__stdcall` c関数とインターフェースするときに「cdecl」を使用してc#p/呼び出しが時々クラッシュするのはなぜですか?

`__stdcall` c関数とインターフェースするときに「cdecl」を使用してc#p/呼び出しが時々クラッシュするのはなぜですか?

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 関数がそれを使用するという (誤った) 仮定につながります。 この不一致により、前述のスタック クリーンアップの問題が発生します。

以上が`__stdcall` c関数とインターフェースするときに「cdecl」を使用してc#p/呼び出しが時々クラッシュするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート