2012-03-04 33 views
3

經過數週的努力,我設法編寫了使用LLVM進行JIT編譯的F#程序。但是,每當我跑我在Visual Studio 2010程序中附帶的調試器(按F5鍵,IE)我得到以下警告:來自LLVM綁定的不平衡堆棧警告

enter image description here

現在,我使用的時候得到這樣的警告,每單的PInvoke呼叫我Windows 7的上網本,但我只使用我的Windows Vista桌面時撥打一些電話。

其他人觸及此問題似乎已通過向要求ANSI字符串的PInvoke調用或CDecl調用約定添加屬性來解決此問題。我發現更改調用約定可以修復Windows Vista桌面上的警告,但是沒有可用的調用約定(或ANSI格式字符串)修復Windows 7上網本上的警告。任何想法如何解決這一問題?

請注意,這兩臺機器都是完全32位的x86。

編輯

人們張貼評論,要求repros。重現此問題最簡單的方法是按照我記錄的here指示安裝LLVM和llvm-fs,並運行給出的任何示例程序。他們都在我的上網本上打電話給LLVM的所有問題。

替代地,下面的代碼(從LLVM-FS導出)應REPRO問題,而不需要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

發表一個小例子來說明問題。 – 2012-03-04 15:32:11

+0

如果你不知道你究竟在做什麼*,恐怕我們無法幫助你。向我們展示您的代碼(小部分),展示問題! – svick 2012-03-04 15:45:18

+0

你是用單聲道還是MS搭建的FSC構建F#代碼? – 2012-03-04 15:55:50

回答

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仍將始終調試項目時使用它。 更糟糕的是,嚴格檢查只在默認情況下在.NET 4.0的x86版本中,而不是在x64版本中,所以在64位機器上工作得很好的程序集可能會在32位機器上崩潰。

MSDN有關於pInvokeStackImbalance MDAthis blog post的更多信息,還提供了有關在調試過程中爲何出現問題的更多詳細信息。

編輯:我只是注意到你編輯你的問題,包括一個代碼示例。這種證實我懷疑PInvoke簽名是錯誤。如果將簽名從extern void *moduleCreateWithNameNative(string ModuleID)更改爲extern LLVMModuleRef* moduleCreateWithNameNative(string ModuleID),會發生什麼情況?

它看起來還有一個編譯器錯誤在這裏工作--F#不應該讓你定義一個名爲*moduleCreateWithNameNative的方法。我猜想它允許它(不管什麼原因),所以函數的返回類型編譯爲void - 並且當本地方法試圖返回一個值(指向LLVMModuleRef結構體的指針)時,CLR會被絆倒並崩潰。

+0

這兩臺機器都是.NET 4.0,但它在一個上運行正常,但在另一個上的每個呼叫上都有條形碼。 – 2012-03-04 17:31:35