C ++中的安全交叉编译器ABI?

Posted

技术标签:

【中文标题】C ++中的安全交叉编译器ABI?【英文标题】:Safe cross-compiler ABI in C++? 【发布时间】:2019-06-03 08:44:05 【问题描述】:

在 cpp 核心指南中,有一个(部分不完整)statement:

I.26:如果您想要一个交叉编译器 ABI,请使用 C 风格的子集

原因

不同的编译器为类、异常处理、函数名和其他实现细节实现不同的二进制布局。

例外

您可以使用一些精心挑选的高级 C++ 类型来精心设计接口。见???。

交叉编译器 ABI 的一个很好的例子是插件系统。假设我希望它尽可能对 C++ 友好。

界面:

class Plugin

public:
    virtual ~Plugin() 

    enum class Type A, B, C;
    virtual Plugin::Type getType() const = 0;

    virtual void doWork() = 0;
;

// C-style for the main plugin entry function
typedef Plugin* (*PluginCreateCallback)();
typedef void (*PluginDestroyCallback)(Plugin*);
extern "C" void pluginMain(PluginCreateCallback* createCb, PluginDestroyCallback* destroyCb);

插件实现(使用编译器#1 编译)可能如下所示:

class MyPlugin: public Plugin

    Plugin::Type getType() const override return Plugin::Type::A;
    void doWork() ...
;

Plugin* myCreateCb()

    return new MyPlugin();


void myDestroyCb(Plugin* plugin)

    delete plugin;


extern "C" void pluginMain(PluginCreateCallback* createCb, PluginDestroyCallback* destroyCb)

    *createCb = &myCreateCb;
    *destroyCb = &myDestroyCb;

应用程序实现(使用编译器#2 编译)将包含以下内容:

handle->pluginMain(&createCb, &destroyCb);
Plugin* plugin = createCb();
plugin->doWork();
destroyCb(plugin);

问题

在交叉编译器环境中使用像Plugin 这样的类是否安全? (它在内存中的表示方式是否相同?) 扩展 Plugin::Type 枚举会影响 Plugin 类的表示方式吗? 更一般地说,那些“精心挑选的高级 C++ 类型”是什么?

更新

在 Martin Reddy 的“API 设计”一书第 12 章中,似乎指定了使用插件接口的确切场景:

实现抽象基类的虚方法可以隔离 来自 ABI 问题的插件,因为虚拟方法调用通常表示为索引 一个类的 vtable。从理论上讲,vtable 格式在编译器之间可能会有所不同,但实际上这 往往不会发生。

由此,我了解到在编译器之间使用抽象类通常是安全的,但标准绝对不能保证。

【问题讨论】:

“不同的编译器实现不同的 ... 函数名称” - 除非两个编译器完全同意 name mangling 规则,否则您的示例中的 plugin->doWork(); 将会崩溃。 (***引用:“C++ 语言没有定义标准的装饰方案,所以每个编译器都使用自己的。”)所以理论上答案是否定的。你有一些现实生活中的平台吗?有些可能有针对多个编译器的交叉编译器 ABI。 @jakub_d 是的,可能是这样。对于平台,我会说 Windows、Linux 和 Mac(我认为 MSVC、gcc/mingw 和 clang 占据了编译器市场的最大部分)。但我会保持这个问题与平台无关。 看到this question询问相关异常后,我打开了一个issuegithub.com/isocpp/CppCoreGuidelines/issues/…,答案似乎是没有这样的异常,这一段将被删除。 @Holt 太好了,你能把这个作为答案发布吗? 【参考方案1】:

我打开了issue on Github 以获取此类异常的示例,而Herb Sutter's answer 是:

编辑调用:我们没有指向的引用,所以我们同意我们应该删除异常。谢谢!

这个例外段落has now been removed来自规范。

【讨论】:

以上是关于C ++中的安全交叉编译器ABI?的主要内容,如果未能解决你的问题,请参考以下文章

clion中C项目交叉编译说明

“usr/include/dbus-1.0”对于maliit框架中的交叉编译是不安全的

如何优化C ++代码的以下片段 - 卷中的零交叉

多目标遗传算法 ------ NSGA-II (部分源码解析) 交叉操作 crossover.c

C++ Linux 到 Windows 交叉编译错误

SQL各种连接——自连接内连接外连接交叉连接的使用