2012-10-27 73 views
2

在Windows上,當使用g ++ 4.6(mingw)和-std = C++ 0x並且與第三方靜態庫(供應商提供的mingw使用)進行鏈接時,該應用程序可以正常工作。當我切換到g ++ 4.7.2(mingw)以便我可以使用-std = C++ 11時,應用程序生成良好,但運行時崩潰。如果我註釋掉對供應商提供的庫的調用,那麼它不會崩潰。我詢問了圖書館供應商的客戶支持,並被告知這不被支持。升級到g ++ 4.7(支持C++ 11):任何ABI不兼容?

我的問題是,「有沒有任何ABI不兼容」,當轉到更新版本的g ++編譯器?它不向後兼容嗎?新版本的編譯器是否應該與現有的和傳統的第三方靜態庫一起工作?

請注意,這隻發生在Windows(mingw)平臺上。在Linux上運行良好。

我增加了更多的信息在這:

有沒有人使用奇爾卡特的MinGW的C++在Windows應用程序的源編譯使用g ++ 4.7.2與-std = C++ 11的編譯選項(靜態)庫?當訪問Chilkat api時,該應用程序崩潰(例如CkString對象被實例化)。適用於g ++ 4.6.2(我使用std = C++ 0x)。 在使用g ++ 4.7.2的Linux上,此程序正常工作。如果從4.6.2移動到4.7.2時存在ABI不兼容問題,那麼它也不適用於Linux,對吧?爲什麼供應商爲了和MINGW一起使用而創建的靜態庫chilkat-9.3.2/lib/libchilkat.a會關心程序的其餘部分是否使用最新的g ++編譯器編譯---這是ABI中的MINGW特定更改嗎?

 
#include <windows.h> 
#include <stdio.h> 
#include <CkString.h> 
int main(int argc, char *argv[]) { 
    printf("test chilkat\n"); 
    CkString str1; 
    printf("test done\n"); 
} 
 
gdb -i=mi test_chilkat.exe 
Starting program: test_chilkat.exe 
[New Thread 4704.0x1a44] 

Program received signal SIGSEGV, Segmentation fault. 
0x00404442 in CkObject::CkObject()() 
+0

是的。請參閱http://gcc.gnu.org/gcc-4.7/changes.html我相信這是一個僅限於庫的更改(特別是在std :: list和std :: pair中)並且僅影響C++ 11模式。 – dajames

+1

那麼,GCC 4.7.2實際*恢復* ABI與GCC 4.6的兼容性。所以OP在這裏遇到的可能是不同的。 –

+2

Linux ABI兼容性和Windows ABI兼容性完全不同。一般來說,我不指望任何Windows GCC版本來維護任何類型的ABI。 – rubenvb

回答

4

的MinGW 4.6.2絕對生成不同的代碼來調用CkString構造比4.7.2。

這是我用來編譯你的測試程序的彙編代碼文件(其中./include是奇爾卡特頭的位置)的命令行:

g++ -I ./include -S -masm=intel -std=gnu++0x test.cpp 

這裏是由兩個printf()電話bookended註釋反彙編( GCC生成puts()呼叫)。

  • 4.6.2:

    call _puts 
    
    lea eax, [esp+28]   ; eax gets pointer to `str1` being constructed 
    mov DWORD PTR [esp], eax ; put the `str1` pointer on the stack 
    call __ZN8CkStringC1Ev ; call `CkString::CkString()` ctor 
    
    mov DWORD PTR [esp], OFFSET FLAT:LC1 
    call _puts 
    
  • 4.7.2:

    call _puts 
    
    lea eax, [esp+28]   ; eax gets pointer to `str1` being constructed 
    mov ecx, eax    ; ecx gets `str1` "this" pointer 
    LEHB0: 
    call __ZN8CkStringC1Ev ; call `CkString::CkString()` ctor 
    
    mov DWORD PTR [esp], OFFSET FLAT:LC1 
    call _puts 
    

正如你所看到的,4.6.2可以通過 「this」 指針構造(這是奇爾卡特圖書館期望的)。 4.7.2傳遞ecx中的「this」指針。

它看起來像從4.7.0開始。 MinGW將C++類成員調用約定改爲__thiscall。見http://mingw-users.1079350.n2.nabble.com/MinGW-GCC-4-7-0-released-td7578133.html

看起來你可以使用-mabi=sysv選項,這讓你對我的測試程序的工作將覆蓋默認:

C:\temp>g++ --version 
g++ (GCC) 4.7.2 
... 

C:\temp>g++ -mabi=sysv -I ./include -g -Wl,--enable-auto-import test.cpp -o test.exe libchilkat-9.3.2.a 

C:\temp>test 
test chilkat 
test done 

然而,你可能會買自己與其他庫比較麻煩更復雜的程序 - 例如,你幾乎肯定需要至少重建libstdc++.a

我會按奇爾卡特開發商爲4.7.x庫多一點...

+0

哦,很好找。它*應該*,假設這是唯一的問題,chilkat不會調用任何libstdC++成員函數,也可以通過修改頭文件來解決它,明確地爲每個成員函數的調用約定添加適當的__attribute__。 – hvd

+0

Michael,感謝您花時間詳細調查並比較2個編譯器的彙編輸出,對它們進行註釋並提供解決方案(-mabi = sysv),這是一個很好的解決方法。對此,我真的非常感激。正如你所警告的,這適用於我的示例測試程序,但不適用於我的實際程序,它會崩潰。等待供應商回覆。 –

3

我的供應商(奇爾卡特),並回答巴布是不是它的「不支持」 ,但它「尚未支持」。

在每個奇爾卡特版本之間,都有不可避免的新系統需要支持。這些都需要時間(在奇爾卡特)來生產建築和配送的自動化系統。要處於新事物的最前沿,並期望它立即得到奇爾卡特的支持,這有點不合理。目前,奇爾卡特正在計劃支持以下新系統:Windows Phone 8,Embarcadero XE3,Mono(跨平臺的Windows,Linux,MAC OS X,iOS,Android等),任何新的Perl,Python,PHP等版本,例如Python 3.3.0,Android for MIPS和x86。奇爾卡特還以其他方式提供API,這些方式不一定是「新」的,例如以類似於「C」API的方式提供DLL/.so/.dylib功能庫。

作爲跨平臺API合理性的一部分,重要的內部開發正在進行中。例如,「Ck *」C++頭文件和實現將完全生成。 .NET程序集管理的頭文件和實現也是如此,每個頭文件和實現都調用相同的內部實現。這將做兩件事情(1)消除平臺之間的任何不一致,(2)允許對外層進行改進/改變。例如,如果需要爲每個C++類方法添加一個調用約定修飾符。也許增加「_ stdcall」或「 _chilkat_call」,其中「__chilkat_call」可以在一個地方定義爲無,「_ stdcall」或「_thiscall」將有所幫助。當生成Ck *頭文件和方法時,這將是可能的。

總之,您的需求將在未來幾個月內得到支持,而不是在此刻。我很抱歉,但我希望你明白。