3

数週間の努力の結果、JIT コンパイルに LLVM を使用する F# プログラムを作成することができました。ただし、Visual Studio 2010 でデバッガーをアタッチして (つまり、F5 キーを押して) プログラムを実行すると、次の警告が表示されます。

ここに画像の説明を入力

現在、Windows 7 ネットブックを使用している場合は PInvoke 呼び出しごとにこの警告が表示されますが、Windows Vista デスクトップを使用している場合は一部の呼び出しでのみ表示されます。

CDeclこの問題にぶつかった他の人々は、ANSI 文字列または呼び出し規約を要求する PInvoke 呼び出しに属性を追加することで解決したようです。呼び出し規約を変更すると、Windows Vista デスクトップでは警告が修正されますが、使用可能な呼び出し規約 (または ANSI フォーマット文字列) のいずれも、Windows 7 ネットブックでは警告を修正しないことがわかりました。これを修正する方法はありますか?

両方のマシンが完全に 32 ビット x86 であることに注意してください。

編集

人々はリプロを求めるコメントを投稿しています。この問題を再現する最も簡単な方法は、ここに記載されている手順に従って LLVM と llvm-fs をインストールし、指定されたサンプル プログラムのいずれかを実行することです。私のネットブックでの LLVM へのすべての呼び出しで、この問題が発生します。

または、次のコード (llvm-fs から派生) は、llvm-fs を必要とせずに問題を再現する必要があります。

open System.Runtime.InteropServices

[<DllImport("LLVM-3.0.dll",
            EntryPoint="LLVMModuleCreateWithName",
            CharSet=CharSet.Ansi,
            CallingConvention=CallingConvention.Cdecl)>]
extern void *moduleCreateWithNameNative(string ModuleID)

let mdl = moduleCreateWithNameNative "foo"

元の C ヘッダー ファイルの対応する定義は次のとおりです。

typedef struct LLVMOpaqueModule *LLVMModuleRef;
...
LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID);
4

1 に答える 1

4

.NET 4.0 以前のバージョンをターゲットにしていますか?

私が尋ねる理由は、Pinvoke 署名の非常に厳密なチェックを実行する CLR のセキュリティ/安定性機能があるためです。.NET 2.0 から存在していましたが、.NET 4.0 まではデフォルトでオフでした。

動作の切り替えにより、多くの開発者があなたと同じ問題を報告しています。それらのバインディングは .NET 2.0/3.5 では問題なく動作しましたが、.NET 4.0 用にコンパイルするとエラーが発生し始めました。実際の問題は、以前のバージョンの .NET では、わずかにバグのある PInvoke 署名が問題なく機能していたことです。厳密なチェックがデフォルトでオンになっているため、バグが現れ始めています。

注意すべきもう 1 つの点は、マシンの構成を変更して .NET 4.0 でこの動作を無効にした場合でも、Visual Studio はプロジェクトのデバッグ時に常にそれを使用することです。さらに悪いことに、厳密なチェックは既定で .NET 4.0 の x86 バージョンでのみオンになっており、x64 バージョンではオンになっていないため、64 ビット マシンで正常に動作するアセンブリが 32 ビット マシンでクラッシュする可能性があります。

MSDN には、pInvokeStackImbalance MDAに関する詳細情報があり、このブログ投稿には、デバッグ プロセス中に問題が発生する理由についての詳細も記載されています。

編集:コード例を含めるように質問を編集したことに気付きました。この種のことは、PInvoke 署名が少し間違っているという私の疑いを裏付けるものです。署名を からextern void *moduleCreateWithNameNative(string ModuleID)に変更するとどうなりextern LLVMModuleRef* moduleCreateWithNameNative(string ModuleID)ますか?

また、ここでコンパイラのバグが発生しているようです。F# では、 というメソッドを定義することはできません*moduleCreateWithNameNative。(何らかの理由で)それを許可していると思いますので、関数の戻り値の型は次のようにコンパイルされますvoid-そして、ネイティブメソッドが値(LLVMModuleRef構造体へのポインター)を返そうとすると、CLRがつまずき、クラッシュします。

于 2012-03-04T17:26:06.573 に答える