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?的主要内容,如果未能解决你的问题,请参考以下文章
“usr/include/dbus-1.0”对于maliit框架中的交叉编译是不安全的