问题
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() ()
回答1:
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...
回答2:
I'm the vendor (Chilkat), and the answer to Babu wasn't that it's "not supported", but that it's "not yet supported".
In between each Chilkat release, there are inevitably new systems that need support. Each of these takes time (at Chilkat) to produce the automated systems for building and distribution. To be on the bleeding edge of something new, and expect it to be immediately supported by Chilkat is somewhat unreasonable.
At the current time, Chilkat is planning support for the following new systems: Windows Phone 8, Embarcadero XE3, Mono (cross-platform for Windows, Linux, MAC OS X, iOS, Android, etc.), any new versions of Perl, Python, PHP, etc, such as Python 3.3.0, Android for MIPS and x86. Chilkat is also to provide API's in other ways that are not necessarily "new" such as providing a DLL/.so/.dylib functional lib in a way similar to the "C" API.
As part of the cross-platform API rationality, significant internal development is underway. For example, the "Ck*" C++ headers and implementations are going to be completely generated. The same goes for the .NET assembly managed headers and implementations, each of which calls down into the same internal implementations. This will do two things (1) iron out any inconsistencies between platforms, and (2) allow for improvements/changes in the outer-layer to be made. For example, if it's necessary to add a calling convention modifier to each of the C++ class methods. Perhaps adding "_stdcall" or "_chilkat_call" where "__chilkat_call" can be defined in one place to be either nothing, "_stdcall" or "_thiscall" would help. This will be possible when the Ck* headers and methods are generated..
In summary, your need will be supported in the months ahead, just not at this immediate moment. I'm sorry for this, but I hope you understand.
来源:https://stackoverflow.com/questions/13100324/upgrade-to-g-4-7-with-c11-support-any-abi-incompatibility