来自LLVM绑定的不平衡堆栈警告

时间:2012-03-04 15:13:41

标签: c# f# pinvoke llvm llvm-fs

经过数周的努力,我成功编写了使用LLVM进行JIT编译的F#程序。但是,每当我在附带调试器的Visual Studio 2010中运行我的程序时(即通过按F5),我会收到以下警告:

enter image description here

现在,在使用我的Windows 7上网本时,每次PInvoke调用都会收到此警告,但在使用Windows Vista桌面时,我只能接听一些电话。

其他遇到此问题的人似乎通过向请求ANSI字符串或CDecl调用约定的PInvoke调用添加属性来解决此问题。我发现更改调用约定会修复Windows Vista桌面上的警告,但是没有可用的调用约定(或ANSI格式字符串)修复了我的Windows 7上网本上的警告。任何想法如何解决这个问题?

请注意,这两台计算机完全是32位x86。

修改

人们正在发表评论,要求提供重复报道。重现此问题的最简单方法是按照我记录的here的说明安装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);

1 个答案:

答案 0 :(得分:4)

您的目标是.NET 4.0还是早期版本?

我问的原因是CLR有一个安全性/稳定性功能,可以对Pinvoke签名进行额外严格的检查;它自.NET 2.0以来一直存在,但在.NET 4.0之前默认关闭。

行为转换导致许多开发人员报告了与您相同的问题;他们的绑定在.NET 2.0 / 3.5上运行得很好,但是在为.NET 4.0编译时开始抛出错误。实际上,问题在于.NET的早期版本允许轻微错误的PInvoke签名无问题地工作;现在默认情况下严格检查,错误开始出现。

另外需要注意的是,即使您更改了计算机上的配置以在.NET 4.0中禁用此行为,Visual Studio仍然始终在调试项目时使用它。 更糟糕的是,严格检查仅在x86版本的.NET 4.0中默认启用,而不是x64版本,因此在64位计算机上运行良好的程序集可能会在32位计算机上崩溃

MSDN有关于pInvokeStackImbalance MDAthis blog post的更多信息,还提供了有关在调试过程中问题突然出现的更多详细信息。

编辑:我刚刚注意到您编辑了您的问题以包含代码示例。这种情况证实了我对PInvoke签名轻微错误的怀疑。如果您将签名从extern void *moduleCreateWithNameNative(string ModuleID)更改为extern LLVMModuleRef* moduleCreateWithNameNative(string ModuleID)会怎样?

在这里看起来还有一个编译器错误--F#不应该允许你定义一个名为*moduleCreateWithNameNative的方法。我猜它是允许的(无论出于何种原因),因此函数的返回类型编译为void - 当本机方法尝试返回一个值(指向LLVMModuleRef结构的指针)时CLR被绊倒并崩溃。