2

在 Windows 上,当使用 g++ 4.6 (mingw) 和 -std=c++0x 并与第三方静态库(由供应商提供用于 mingw 的)链接时,应用程序运行良好。当我切换到 g++ 4.7.2 (mingw) 以便可以使用 -std=c++11 时,应用程序构建良好,但运行时崩溃。如果我注释掉对供应商提供的库的调用,那么它不会崩溃。我询问了图书馆供应商的客户支持,并被告知不支持此功能。

我的问题是,在使用更新版本的 g++ 编译器时,“是否存在任何 ABI 不兼容性”?它不向后兼容吗?新版本的编译器不应该与现有和遗留的第 3 方静态库一起使用吗?

请注意,这只发生在 Windows (mingw) 平台上。在 Linux 上运行良好。

我已经添加了更多信息:

有没有人在 Windows 应用程序中使用过 Chilkat 的 MinGW C++(静态)库,其源代码是用 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("测试chilkat\n");
  CKString str1;
  printf("测试完成\n");
}
gdb -i=mi test_chilkat.exe
启动程序:test_chilkat.exe
[新线程 4704.0x1a44]

程序收到信号 SIGSEGV,分段错误。
0x00404442 在 CkObject::CkObject() ()
4

2 回答 2

4

MinGW 4.6.2 肯定会生成与CkString4.7.2 不同的代码来调用构造函数。

这是我用来将您的测试程序编译为汇编代码文件的命令行(./includeChilkat 标头的位置在哪里):

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

printf()以下是由两个调用(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”指针传递给堆栈上的构造函数(这是 Chilkat 库所期望的)。4.7.2 将“this”指针传入ecx.

它看起来像从 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至少需要重新构建。

我会向 Chilkat 开发人员要求更多 4.7.x 库...

于 2012-10-30T07:59:15.313 回答
3

我是供应商 (Chilkat),对 Babu 的回答不是“不支持”,而是“尚未支持”。

在每个 Chilkat 版本之间,不可避免地会有需要支持的新系统。每一个都需要时间(在 Chilkat)来生产用于构建和分发的自动化系统。站在新事物的最前沿,并期望它立即得到 Chilkat 的支持,这有点不合理。

目前,Chilkat 计划支持以下新系统:Windows Phone 8、Embarcadero XE3、Mono(跨平台适用于 Windows、Linux、MAC OS X、iOS、Android 等)、任何新版本的 Perl、 Python、PHP 等,例如 Python 3.3.0、Android for MIPS 和 x86。Chilkat 还将以其他不一定是“新”的方式提供 API,例如以类似于“C”API 的方式提供 DLL/.so/.dylib 功能库。

作为跨平台 API 合理性的一部分,重要的内部开发正在进行中。例如,“Ck*”C++ 头文件和实现将完全生成。.NET 程序集托管的标头和实现也是如此,它们中的每一个都调用相同的内部实现。这将做两件事(1)消除平台之间的任何不一致,以及(2)允许对外层进行改进/更改。例如,如果需要为每个 C++ 类方法添加调用约定修饰符。也许添加“ _stdcall ”或“ _chilkat_call”,其中“__chilkat_call”可以在一个地方定义为空,“_ stdcall”或“_thiscall" 会有所帮助。这将在生成 Ck* 标头和方法时成为可能。

总而言之,您的需求将在未来几个月内得到支持,而不是现在。对此我很抱歉,但我希望你能理解。

于 2012-11-01T14:54:48.720 回答