2011-07-21 102 views
1

閱讀了這篇文章F# Versus Mathematics: Part One - Getting Started with BLAS and LAPACK我偶然發現了段落stack imbalance的段落A Warning, Perhaps an Omen什麼是堆棧不平衡?

googled和搜索SO,但只能找到人們在堆棧失衡掙扎,沒有通常的解釋。

獎勵題: 是否隻影響F#還是用C,C++,Python和Java等的普遍問題?

p.s.請更改問題的標籤,如果必要

+2

簡而言之,這意味着您正在調用帶有錯誤簽名的非託管函數。 – Daniel

+1

它影響任何帶有[FFI](http://en.wikipedia.org/wiki/Foreign_function_interface)語言的非託管代碼。 – Daniel

回答

8

當用於跟蹤被調用函數,參數和返回值的數據結構損壞或未對齊時,會發生堆棧不平衡。

大多數情況下,堆棧是一個內存指針,用於存儲當前函數調用返回調用方時控制將恢復的地址。這裏有不同的變體,有時函數的參數也會附加到堆棧,以及返回值。這裏最重要的是,主叫方和被叫方應該就被叫方退出時如何恢復到之前的狀態達成一致。該協議通常稱爲呼叫公約

在.NET中,堆棧不平衡是純粹的託管代碼中罕見的不存在的問題。但是,在調用非託管代碼時,這可能是一個常見問題,因爲您需要告訴編譯器該如何調用該方法,這意味着應該如何按照調用約定清理堆棧。

在windows上,有幾個標準調用約定覆蓋了大量的調用情況。

STDCALL - 被叫方將在退出修復堆棧。
fastcall - 可能不需要將堆棧固定在返回地址之外,而是使用CPU寄存器來傳遞參數。
cdecl - 調用者將在被調用函數返回後修復堆棧。

的正式參考,請訪問:Argument Passing and Naming Conventions @ MSDN

這也感興趣:X86 calling convention list @ Wikipedia

在給定的發展領域,這往往不是一個問題。每種語言通常都有一個隱含於所有方法調用的約定。 C/C++使用相同的約定來調用C/C++調用,Python用於其他Python調用等。在跨域時,如果一個域不使用另一個域,則可能會成爲問題。也許在Windows中最常見的是,調用與「C」風格聲明(cdecl)一起導出的函數在調用時會導致不平衡的堆棧(或更糟糕的情況),就好像它具有stdcall約定,這是WINAPI(windows系統)調用識別的方法。

+0

+1我認爲我們的問題是由於調用約定 – jglouie

+0

+1對於非常通用且語言不可知的描述以及具體示例。 – Bedasso

4

我們剛剛看到這個有一天

(用C#和C++編組),我是指你從一個MSDN頁的文字:

的pInvokeStackImbalance在CLR檢測到平臺 調用調用之後的堆棧深度與預期堆棧深度不匹配(假定調用DllImportAttribute屬性中指定的調用 約定)以及 調用調用助理(MDA)時調用的調用助理(MDA)爲 聲明管理的簽名中的參數。

我意識到這是針對特定的編譯器警告,但該頁面提供了關於堆棧不平衡的一些信息,是什麼導致它,什麼症狀,以及如何解決它。正如丹尼爾所說,這通常是由於託管和非託管的簽名不匹配。

希望這會有所幫助。

+0

+1,用於在.NET中處理此問題的良好鏈接 – meklarian