【问题标题】:Undocumented ABI changes of std::function between GCC-4 and GCC-5/6/7/8/9, how to make a .so working with devtoolset-4/6/7/8/9?GCC-4 和 GCC-5/6/7/8/9 之间 std::function 的无证 ABI 更改,如何使 .so 与 devtoolset-4/6/7/8/9 一起使用?
【发布时间】:2020-06-03 02:53:37
【问题描述】:

使用 _GLIBCXX_USE_CXX11_ABI=0 GCC-4 的 std::function 与 GCC-5 及以下版本不同。

下面的代码告诉你事实:

==> lib.cc

#include <functional>

std::function<int(const void*p)> holder;

int run_holder(const void *p)
{
    return holder(p);
}

==> main.cc

#include <stdio.h>
#include <functional>

extern int run_holder(const void*p);
extern std::function<int(const void*p)> holder;

int foo(const void* p)
{
    printf("p=%p\n", p);
    return 0;
}

int main()
{
    holder = foo;
    foo((void*)0x12345678);
    holder((void*)0x12345678);
    run_holder((void*)0x12345678);
}

==> make.sh

#!/bin/bash
GCC4=/usr/bin/g++
GCCN="scl enable devtoolset-5 -- g++"

$GCC4 -std=c++11 -c -g lib.cc -shared -o libfoo.so &&
$GCCN -std=c++11 -L. -lfoo -g main.cc -o a.out &&
LD_LIBRARY_PATH=. ./a.out

预期结果,类似于:

p=0x12345678
p=0x12345678
p=0x12345678

实际结果:

p=0x12345678
./make.sh: line 6:   973 Segmentation fault      LD_LIBRARY_PATH=. ./a.out

原因是std::function的实现在没有文档的情况下发生了变化。

gcc4: /usr/include/c++/4.8.2/functional:2430

typedef _Res (*_Invoker_type)(const _Any_data&, _ArgTypes...);

gcc5: /opt/rh/devtoolset-4/root/usr/include/c++/5.3.1/functional:2226 gcc8: /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/std_function.h:609

using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);

所以我不能使用由 gcc4 编译并由 gcc5/6/7/8 使用的 std::function 编写 .so。没有像_GLIBCXX_USE_CXX11_ABI这样的宏可以控制行为。

【问题讨论】:

    标签: c++11 gcc abi


    【解决方案1】:

    所以我不能使用由 gcc4 编译并由 gcc5/6/7/8 使用的 std::function 编写 .so。

    正确。 Red Hat 和 GCC 项目都没有声称这是可能的,恰恰相反。 GCC 4.x 中的 C++11 支持不完整且不稳定,并且受 ABI 更改和 API 更改的影响。您尝试做的事情从未得到支持。

    我已在https://stackoverflow.com/a/49119902/981959 对此进行了更详细的解释

    Developer Toolset 文档也涵盖了它(强调我的):

    "C++11 或 C++14 模式下的编译器仅保证与 C++11 或 C++14 模式下的另一个编译器兼容,前提是它们来自同一发行系列(对于Red Hat Developer Toolset 6.x 中的示例)。
    ...
    “当所有使用相应标志编译的 C++ 对象均已使用 Red Hat Developer Toolset 6 或更高版本构建时,Red Hat Developer Toolset 支持使用 C++14 语言版本。由系统 GCC 在其默认模式 C++98 也兼容,但使用系统 GCC 在 C++11 或 C++14 模式下编译的对象不兼容。"

    没有像_GLIBCXX_USE_CXX11_ABI这样的宏可以控制行为。

    我们不提供宏来控制不受支持且无法工作的内容。

    如果您想将 C++11 与 GCC 版本的混合使用,您需要使用对 C++11 具有稳定、非实验性支持的版本。所以不是 GCC 4.x。

    【讨论】:

    • C++14 std 怎么样,从 GCC 的哪个版本可以认为 ABI 是稳定的?
    • GCC 6,但我认为实际上在 5 和 6 之间没有 ABI 更改。但请注意,官方支持的 Developer Toolset 版本组合更为保守,因此请阅读文档。
    猜你喜欢
    • 2021-05-30
    • 2021-02-15
    • 2022-10-08
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-07
    相关资源
    最近更新 更多