问题描述
在Windows上,当使用g ++ 4.6(mingw)和-std = c ++ 0x并链接到第三方静态库(由供应商提供用于mingw)时,应用程序工作正常。当我切换到g ++ 4.7.2(mingw),以便我可以使用-std = c ++ 11,应用程序构建正常,但运行时崩溃。如果我注释掉对供应商提供的库的调用,那么它不会崩溃。我询问客户对图书馆供应商的支持,并被告知这不受支持。
我的问题是,有任何ABI不兼容性 g ++编译器?是不是向后兼容?不是较新版本的编译器应该与现有的和传统的第三方静态库一起工作?
请注意,这只会发生在Windows(mingw)平台上。
有任何人使用Chilkat的MinGW C ++()静态)库在一个Windows应用程序的源代码是用g ++ 4.7.2编译的-std = c ++ 11编译选项?访问Chilkat API时,应用程序崩溃(例如CkString对象被实例化)。在g ++ 4.6.2(其中我使用std = c ++ 0x)上工作得很好。
在Linux上使用g ++ 4.7.2这个程序工作正常。如果从4.6.2移动到4.7.2时有ABI不兼容,那么它不应该在Linux上工作,对吧?为什么静态库chilkat-9.3.2 / lib / libchilkat.a由供应商创建使用MINGW关心如果程序的其余部分用最新的g ++编译器编译---这是一个MINGW在ABI的具体更改吗?
#include< windows.h>
#include< stdio.h>
#include< CkString.h>
int main(int argc,char * argv []){
printf(test chilkat\\\
);
CkString str1;
printf(test done \\\
);
}
gdb -i = mi test_chilkat.exe
启动程序:test_chilkat .exe
[New Thread 4704.0x1a44]
程序接收到SIGSEGV信号,分段故障。
0x00404442在CkObject :: CkObject()()
MinGW 4.6.2肯定是生成不同的代码来调用 CkString
构造函数比4.7.2。
这里是我用的命令行将您的测试程序编译为汇编代码文件( ./ include
是Chilkat头文件的位置):
g ++ -I ./include -S -masm = intel -std = gnu ++ 0x test.cpp
这里是两个 printf()
调用注释的反汇编(GCC生成 puts
$ b
call _puts
lea eax,[esp + 28]; eax获取指向`str1`的指针
mov DWORD PTR [esp],eax;把str1指针放在栈上
call __ZN8CkStringC1Ev;调用`CkString :: CkString()`ctor
mov DWORD PTR [esp],OFFSET FLAT:LC1
call _puts
4.7.2:
call _puts
lea eax,[esp + 28]; eax获取指向`str1`的指针被构造
mov ecx,eax; ecx获取`str1`这个指针
LEHB0:
call __ZN8CkStringC1Ev;调用CkString :: CkString()`ctor
mov DWORD PTR [esp],OFFSET FLAT:LC1
call _puts
如你所见,4.6.2将this指针传递给栈上的构造函数Chilkat库预期)。 4.7.2传递 ecx
中的this指针。
它看起来像从4.7.0开始。 MinGW将C ++类成员调用约定更改为 __ thiscall
。请参见
您似乎可以覆写默认使用 -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
至少。
我会按Chilkat开发者一个4.7.x的库更多...
On Windows, when using g++ 4.6 (mingw) and -std=c++0x and linking with a third party static library (which was provided by the vendor for use with mingw), the application works fine. When I switched to g++ 4.7.2 (mingw) so that I could use -std=c++11, the application builds fine but crashes when run. If I comment out calls to the vendor provided library then it doesn't crash. I asked customer support of the library vendor and was told that this was not supported.
My question is, "Are there any ABI incompatibilities" when going to a newer version of the g++ compiler? Is it not backward compatible? Aren't newer versions of the compiler supposed to work with existing and legacy 3rd party static libraries?
Note that this only happens on Windows (mingw) platform. Works fine on Linux.
I have added more info on this:
Has anyone used Chilkat's MinGW C++ (static) libraries in a windows application whose source is compiled with g++ 4.7.2 with -std=c++11 compile option? The app crashes when Chilkat api is accessed (for e.g CkString object is instantiated). Works fine on g++ 4.6.2 (where I use std=c++0x).On Linux with g++ 4.7.2 this program works fine. If there is ABI incompatibility when moving from 4.6.2 to 4.7.2 then it shouldn't work on Linux also, right? Why would static library chilkat-9.3.2/lib/libchilkat.a created by vendor for use with MINGW care if the rest of the program is compiled with the latest g++ compiler --- is this a MINGW specific change in ABI?
#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() ()
MinGW 4.6.2 is definitely generating different code to call the CkString
constructor than 4.7.2.
Here's the command line I used to compile your test program to the assembly code file (where ./include
is the location of the Chilkat headers):
g++ -I ./include -S -masm=intel -std=gnu++0x test.cpp
Here are annotated disassemblies bookended by the two printf()
calls (which GCC generates as puts()
calls).
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
As you can see, 4.6.2 passes the "this" pointer to the constructor on the stack (which is what the Chilkat library expects). 4.7.2 passes the "this" pointer in ecx
.
It looks like starting with 4.7.0. MinGW changed the C++ class-member calling convention to __thiscall
. See http://mingw-users.1079350.n2.nabble.com/MinGW-GCC-4-7-0-released-td7578133.html
It looks like you can override that default using the -mabi=sysv
option, which makes your test program work for me:
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
However, you'll probably be buying yourself more trouble with other libraries in more complex programs - for example, you'll almost certainly need to rebuild libstdc++.a
at the very least.
I'd press the Chilkat developer for a 4.7.x library a bit more...
这篇关于升级到g ++ 4.7(支持c ++ 11):任何ABI不兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!