Недокументированные изменения ABI в std :: function между G CC -4 и G CC -5 / 6/7/8/9, как сделать так, чтобы он работал с devtoolset-4/6/7/8/9 ? - PullRequest
0 голосов
/ 19 февраля 2020

с _GLIBCXX_USE_CXX11_ABI = 0 std :: function G CC -4 отличается от G CC -5 и следующих версий.

Следующий код показывает вам факт:

==> lib. cc <== </p>

#include <functional>

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

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

==> main. cc <== </p>

#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 / функционал: 2226 gcc8: /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/std_function.h:609

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

так что не могу напишите .so используя std :: function, скомпилированную gcc4 и использованную gcc5 / 6/7/8. Нет такого макроса, как _GLIBCXX_USE_CXX11_ABI, который может управлять поведением.

1 Ответ

2 голосов
/ 24 февраля 2020

Поэтому я не могу написать .so, используя std :: function, скомпилированную gcc4 и использованную gcc5 / 6/7 / 8.

Правильно. Ни Red Hat, ни проект G CC никогда не заявляли, что это возможно, как раз наоборот. Поддержка C ++ 11 в G CC 4.x была неполной и нестабильной, и подверглась изменениям ABI и API. То, что вы пытаетесь сделать, никогда не поддерживалось.

Я объяснил это более подробно на { ссылка }

Документация Developer Toolset также охватывает это (выделение мой):

"Компилятор в режиме C ++ 11 или C ++ 14 гарантированно будет совместим с другим компилятором только в режиме C ++ 11 или C ++ 14, если он из той же серии выпусков (например, из Red Hat Developer Toolset 6.x).
...
"Использование языковой версии C ++ 14 поддерживается в Red Hat Developer Toolset, когда все Объекты C ++, скомпилированные с соответствующим флагом, были созданы с использованием Red Hat Developer Toolset 6 или более поздней версии. Объекты, скомпилированные системой G CC в режиме по умолчанию C ++ 98, также совместимы, , но объекты, скомпилированные с системой G CC в режиме C ++ 11 или C ++ 14, не совместимы."

Нет такого макроса, как _GLIBCXX_USE_CXX11_ABI, который может управлять поведением.

Мы не предоставляем макросы для управления вещами, которые не поддерживаются и не могут работать .

Если вы хотите использовать C ++ 11 с набором версий G CC, вам нужно использовать релиз, который имеет стабильную, не экспериментальную поддержку C ++ 11. Поэтому не G CC 4.х.

...