简体   繁体   English

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

[英]Unbalanced stack warnings from LLVM bindings

After weeks of effort I have managed to write F# programs that use LLVM for JIT compilation. 经过数周的努力,我设法编写了使用LLVM进行JIT编译的F#程序。 However, whenever I run my programs in Visual Studio 2010 with the debugger attached (ie by pressing F5) I get the following warning: 但是,每当我在附带调试器的Visual Studio 2010中运行我的程序时(即通过按F5),我会收到以下警告:

在此输入图像描述

Now, I get this warning for every single PInvoke call when using my Windows 7 netbook but I only get it for some calls when using my Windows Vista desktop. 现在,在使用我的Windows 7上网本时,我收到了每个PInvoke调用的警告,但是在使用我的Windows Vista桌面时,我只获得了一些调用。

Other people hitting this problem seem to have solved it by adding attributes to the PInvoke calls requesting ANSI strings or the CDecl calling convention. 遇到此问题的其他人似乎通过向请求ANSI字符串的PInvoke调用或CDecl调用约定添加属性来解决它。 I found that changing the calling convention fixes the warnings on my Windows Vista desktop but none of the available calling conventions (or ANSI format strings) fix the warnings on my Windows 7 netbook. 我发现更改调用约定会修复Windows Vista桌面上的警告,但是没有可用的调用约定(或ANSI格式字符串)修复了我的Windows 7上网本上的警告。 Any ideas how to fix this? 任何想法如何解决这一问题?

Note that both machines are entirely 32-bit x86. 请注意,这两台机器完全是32位x86。

EDIT 编辑

People are posting comments asking for repros. 人们正在发表评论,要求重新编写。 The simplest way to reproduce this problem is to install LLVM and llvm-fs following the instructions I documented here and run any of the example programs given. 重现此问题的最简单方法是按照我在此处记录的说明安装LLVM和llvm-fs 并运行给定的任何示例程序。 They all exhibit this issue on all calls to LLVM on my netbook. 他们都在我上网本上对LLVM的所有调用中都出现了这个问题。

Alternatively, the following code (derived from llvm-fs) should repro the issue without requiring llvm-fs: 或者,以下代码(从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"

Note that the corresponding definitions in the original C header file are: 请注意,原始C头文件中的相应定义是:

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

Are you targeting .NET 4.0 or an earlier version? 您是针对.NET 4.0还是早期版本?

The reason I ask is there's a security/stability feature for the CLR which performs extra-strict checking of Pinvoke signatures; 我问的原因是CLR有一个安全性/稳定性功能,可以对Pinvoke签名进行额外严格的检查; it's been around since .NET 2.0, but was off by default until .NET 4.0. 它自.NET 2.0以来一直存在,但在.NET 4.0之前默认关闭。

The switch in behavior has resulted in a number of developers reporting the same issue as you are; 行为的转变导致许多开发人员报告了与您相同的问题; their bindings worked just fine on .NET 2.0/3.5, but started throwing errors when compiled for .NET 4.0. 他们的绑定在.NET 2.0 / 3.5上运行得很好,但是在为.NET 4.0编译时开始抛出错误。 In reality, the problem is that prior versions of .NET allowed slightly-buggy PInvoke signatures to work without issue; 实际上,问题在于.NET的早期版本允许轻微错误的PInvoke签名无问题地工作; now that the strict checking is on by default, the bugs are starting to show up. 现在默认情况下严格检查,错误开始出现。

Another thing to note is that even if you change the configuration on your machine to disable this behavior in .NET 4.0, Visual Studio will still always use it when debugging a project. 另外需要注意的是,即使您更改了计算机上的配置以在.NET 4.0中禁用此行为,Visual Studio仍将始终在调试项目时使用它。 Worse yet, the strict checking is only on by default in the x86 version of .NET 4.0, not the x64 version, so an assembly which works just fine on a 64-bit machine may possibly crash on a 32-bit machine. 更糟糕的是,严格检查仅在x86版本的.NET 4.0中默认启用,而不是x64版本,因此在64位计算机上运行良好的程序集可能会在32位计算机上崩溃。

MSDN has more information on the pInvokeStackImbalance MDA and this blog post also provides more detail about why the problem crops up during the debugging process. MSDN有关于pInvokeStackImbalance MDA的更多信息, 此博客文章还提供了有关在调试过程中问题突然显现的更多详细信息。

EDIT: I just noticed you edited your question to include a code example. 编辑:我刚刚注意到您编辑了您的问题以包含代码示例。 This sort of confirms my suspicion about the PInvoke signature being slightly wrong. 这种情况证实了我对PInvoke签名略有错误的怀疑。 What happens if you change the signature from extern void *moduleCreateWithNameNative(string ModuleID) to extern LLVMModuleRef* moduleCreateWithNameNative(string ModuleID) ? 如果您将签名从extern void *moduleCreateWithNameNative(string ModuleID)更改为extern LLVMModuleRef* moduleCreateWithNameNative(string ModuleID)什么?

It also looks like there's a compiler bug at work here -- F# shouldn't allow you to define a method called *moduleCreateWithNameNative . 看起来这里有一个编译器错误--F#不应该允许你定义一个名为*moduleCreateWithNameNative的方法。 I'd guess it is allowing it (for whatever reason), so the return type of your function is compiled as void -- and when the native method tries to return a value (a pointer to an LLVMModuleRef struct) the CLR gets tripped up and crashes. 我猜它是允许的(无论出于何种原因),因此函数的返回类型被编译为void - 当本机方法尝试返回一个值(指向LLVMModuleRef结构的指针)时,CLR会被绊倒和崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM