web-dev-qa-db-ja.com

pinvokestackimbalance-これを修正またはオフにするにはどうすればよいですか?

Vs2008からvs2010に切り替えました。 C++ dllを呼び出すたびに「pinvokestackimbalance」例外が発生することを除いて、まったく同じソリューションです。

この例外は2008年には発生しません。C++ dllおよび呼び出し側アプリケーションに完全にアクセスできます。ピンボークに問題はないようですが、この問題により他の問題のデバッグが不可能になっています。 IDEはこれらのことを私に伝えるために絶えず停止しています。

たとえば、C#署名は次のとおりです。

    [DllImport("ImageOperations.dll")]
    static extern void FasterFunction(
        [MarshalAs(UnmanagedType.LPArray)]ushort[] inImage, //IntPtr inImage, 
        [MarshalAs(UnmanagedType.LPArray)]byte[] outImage, //IntPtr outImage, 
        int inTotalSize, int inWindow, int inLevel);

C++側では次のようになります。

#ifdef OPERATIONS_EXPORTS
#define OPERATIONS_API __declspec(dllexport)
#else
#define OPERATIONS_API __declspec(dllimport)
#endif
extern "C" {


OPERATIONS_API void __cdecl FasterFunction(unsigned short* inArray, 
                                       unsigned char* outRemappedImage,
                                       int inTotalSize, 
                                       int inWindow, int inLevel);

}

これらの例外がスローされる原因となるvs2010とvs2008の違いは何ですか? DllImportディレクティブに別のパラメーターセットを追加する必要がありますか?

70
mmr

最初に、コードが間違っている(常にそうである)ことを理解します。 「pInvokeStackImbalance」はそれ自体例外ではなく、マネージデバッグアシスタントです。 VS2008ではデフォルトでオフになっていましたが、多くの人がオンにしなかったため、VS2010ではデフォルトでオンになっています。 MDAはリリースモードで実行されないため、リリース用にビルドしてもトリガーされません。

あなたの場合、呼び出し規約は間違っています。 DllImportのデフォルトは_CallingConvention.WinApi_で、x86デスクトップコードの_CallingConvention.StdCall_と同じです。 _CallingConvention.Cdecl_である必要があります。

これは、次のように[DllImport("ImageOperations.dll")]行を編集することで実行できます。

_[DllImport("ImageOperations.dll", CallingConvention = CallingConvention.Cdecl)]
_

詳細については、「 このMSDNリファレンス 」を参照してください

133
Stephen Cleary

オフにするには:

  1. Ctrl + Alt + E
  2. [管理されたデバッグアシスタント]で、PInvokeStackImbalanceのチェックを外します。
38
JGogel

この問題を解決するのは、ここではそれほど難しくありませんが、いくつかの方法について言及していますが、上記の私の友人の一部と同じかもしれません。私はPCSCで1週間ほど費やしているSmartcardアプリケーションを使用していますが、多くの変更が最終的に解決されたことに腹を立てています。

私にとって、VS2010用にインストールしたPInvoke拡張機能との連携は、こちらからダウンロードできます http://www.red-gate.com/products/dotnet-development/pinvoke/

それをダウンロードしてインストールし、Visual Studioを閉じて再度開き、メニューバーで拡張機能を見つけます。 enter image description here

エラーが署名が一致しないためである場合は、PInvoke.net> Insert PInvoke Signaturesをクリックするだけです。

新しいウィンドウは次のように表示されます enter image description here

Dllの名前を入力し、検索をクリックすると、検索結果ウィンドウにそのdllのすべての機能が表示されます。特定の機能の署名を取得する機能をクリックします。

その署名を使用すると、その署名、主にデータタイプに従ってプログラムを変更する必要があります。

これにより、callingConventionのような別の問題が発生したり、dllのインポート中に追加の属性を指定する必要があるという問題が解決します。

ハッピーコーディング

8
Vijay Kumbhoje

VS2010を使用しているときにもこの問題が発生しました。概要:Visual Studioのデフォルトでは、「任意のCPU」に対して64ビットコードが使用されます。変数(たとえば、文字列)へのポインターは、外部Dllを呼び出すと64ビットになります。信頼できるすべてのDllは32ビットポインターを使用します。

Dllに問題があると思い込まないでください。

VS設定を変更して、このようなX86コードを生成します(C#の高速バージョン)

  1. [ツール]-> [オプション]に移動します。
  2. [オプション]ダイアログの左下隅にある[すべての設定を表示する]チェックボックスをオンにします。
  3. 左側のツリービューで、[プロジェクトとソリューション]を選択します。
  4. 右側のオプションで、「高度なビルド構成を表示する」というボックスをオンにします。
  5. OKをクリックします。
  6. ビルド->構成マネージャーに移動...
  7. プロジェクトの横の「プラットフォーム」列で、コンボボックスをクリックして「」を選択します。
  8. [新しいプラットフォーム]設定で、[x86]を選択します。
  9. OKをクリックします。
  10. 閉じるをクリックします。

また、12か月ごとにコンピューターの電力が2倍になったにもかかわらず、RAMが1ギガバイトの現在のコンピューターは、4メガバイトの最初の486よりも速くないようです。 64ビットコードの使用について心配する必要はありません。巨大で扱いにくいオブジェクト指向の巨大なタワーの上に構築されているため、高速化も改善もされません。

3
penguinman

CallingConvention is ThisCallでdllを呼び出そうとしましたが、うまくいきました。 BLOB MS Sql Serverで動作するコードを次に示します。

[DllImport("sqlncli11.dll", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.ThisCall)]
            private static extern SafeFileHandle OpenSqlFilestream(
                        string FilestreamPath,
                        UInt32 DesiredAccess,
                        UInt32 OpenOptions,
                        byte[] FilestreamTransactionContext,
                        UInt32 FilestreamTransactionContextLength,
                        Int64 AllocationSize);

詳細: https://msdn.Microsoft.com/en-us/library/system.runtime.interopservices.callingconvention(v = vs.110).aspx

0
Hao Svit