链接gcc 6,gcc 7和gcc 8对象安全吗? [英] Is it safe to link gcc 6, gcc 7, and gcc 8 objects?

查看:180
本文介绍了链接gcc 6,gcc 7和gcc 8对象安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

链接C ++ 17,C ++ 14和C ++ 11对象是否安全询问有关链接使用不同语言标准编译的对象,乔纳森·韦克利(Jonathan Wakely)在该问题上的出色回答解释了gcc / libstdc ++做出的ABI稳定性承诺,以确保这项工作可行。

Is it safe to link C++17, C++14, and C++11 objects asks about linking objects compiled with different language standards, and Jonathan Wakely's excellent answer on that question explains the ABI stability promises that gcc/libstdc++ make to enusure that this works.

还有更多可以在gcc版本之间更改的内容-通过 -fabi-version 。为了简单起见,我有三个目标文件:

There's one more thing that can change between gcc versions though - the language ABI via -fabi-version. Let's say, for simplicity, I have three object files:


  • foo.o ,使用gcc 6.5 c ++ 14
  • 编译,
  • bar.o ,使用gcc 7.4 c ++ 14
  • $编译, b $ b
  • quux.o ,使用gcc 8.3 c ++ 17编译

  • foo.o, compiled with gcc 6.5 c++14
  • bar.o, compiled with gcc 7.4 c++14
  • quux.o, compiled with gcc 8.3 c++17

全部具有各自的默认语言ABI(即10、11和13)。从库的角度来看,根据链接的答案将这些对象链接在一起是安全的。但是从语言ABI的角度来看是否存在可能出错的事情?我有什么需要注意的吗?大部分语言ABI更改似乎都不会引起问题,但是12中的空类类型的调用约定更改可能会吗?

All with the respective default language ABIs (i.e. 10, 11, and 13). Linking these objects together is safe from the library perspective per the linked answer. But are there things that could go wrong from a language ABI perspective? Is there anything I should be watching out for? Most of the language ABI changes seem like they wouldn't cause issues, but the calling convention change for empty class types in 12 might?

推荐答案


大多数语言ABI更改似乎不会引起问题,但是12种空类类型的调用约定更改可能吗?

Most of the language ABI changes seem like they wouldn't cause issues, but the calling convention change for empty class types in 12 might?

更改空类的调用约定可能会在x86-64上引起问题。例如:

The change of the calling convention for empty classes can cause an issue on x86-64. Here's an example:

def.hpp

struct Empty { };

struct Foo {
    char dummy[16];
    int a;

    Foo() : a(42) { }
};

void fn(Empty, Foo);

one.cpp

#include "def.hpp"

int main() {
    fn(Empty(), Foo());
}

two.cpp

#include <stdio.h>
#include "def.hpp"

void fn(Empty e, Foo foo) {
    printf("%d\n", foo.a);
}

现在,如果您使用G ++ 8编译这些文件,且ABI分别为11和12 ,例如:

Now, if you compile these with G++ 8 with differing ABIs of 11 and 12, for example:

g++ -c -fabi-version=11 one.cpp
g++ -c -fabi-version=12 two.cpp
g++ one.o two.o

结果 a.out 不会打印预期的 42

原因是旧的ABI(11)在堆栈上为 Empty()保留了空间,而新的ABI(12)没有。因此 foo 的地址在调用方和被调用方之间将有所不同。

The reason is that the old ABI (11) reserves space for Empty() on the stack, but the new ABI (12) doesn't. So the address of foo will differ between the caller and the callee side.

(注意:我包括了 Foo :: dummy ,所以 Foo 是使用堆栈而不是寄存器传递的。如果 Foo 是使用寄存器传递的,那不会有问题。)

(Note: I've included Foo::dummy so Foo gets passed using the stack instead of registers. If Foo was passed using registers, there would be no problem.)

这篇关于链接gcc 6,gcc 7和gcc 8对象安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆