#c #exception #shared-libraries #visibility
#c #исключение #общие библиотеки #видимость
Вопрос:
У меня сбой CI в моей программе, которая использует Boost.Варианты программы. Не удается перехватить исключение, созданное внутри разделяемой библиотеки Boost. Но это происходит только в OSX.
Проблема сводится к трансграничной обработке исключений с общими объектами и скрытой видимостью.
Что происходит:
- Boost — это сборка со скрытой видимостью, генерируемое исключение помечается видимостью по умолчанию
- При использовании исключение в заголовке Boost ничем не помечается
- Когда потребляющая программа создается с видимостью по умолчанию, все работает должным образом
- При сборке программы-потребителя со скрытой видимостью не удается перехватить исключение только в OSX (Windows и Linux работают с несколькими компиляторами)
Я нашел: https://gcc.gnu.org/wiki/Visibility
Видимость символа по умолчанию «по умолчанию», но если компоновщик обнаруживает только одно скрытое определение — только одно — этот символ typeinfo становится постоянно скрытым (помните правило ODR — one definition стандарта C ).
Итак, в этом (и в остальной части абзаца исключения C ) говорится, что поведение OSX — это то, что ожидается.
Это также должно быть показано «Версией 3» http://www.ce.unipr.it/people/medici/visibility_and_shared_object.html что, по сути, является MWE:
my_hidden_exception.h
class my_exception {
public:
virtual ~my_exception() throw() { }
virtual const char*
what() const throw() { return "my_exception"; }
};
main.cpp:
#include <iostream>
#include "my_hidden_exception.h"
int my_object();
int main()
{
try{
my_object();
}
catch(my_exception amp; e)
{
std::cout << e.what() << std::endl;
}
}
shared.cpp:
#include "my_hidden_exception.h"
int __attribute__ ((visibility("default"))) my_object()
{
throw my_exception();
}
Скомпилируйте и запустите с
g -shared -o libshared.so shared.cpp -fvisibility=hidden -fvisibility-inlines-hidden
g -o main main.cpp -lshared -L. -fvisibility=hidden -fvisibility-inlines-hidden
./main
Моя проблема сейчас в том, что я не могу воспроизвести это с помощью любого GCC (7, 10) или Clang (6, 9), которые я тестировал, во всех случаях исключение успешно перехвачено, что, согласно всем источникам, должно быть невозможно.
Кто-нибудь может объяснить, чего мне здесь не хватает? Как я могу «принудительно» корректировать поведение в Linux для лучшего тестирования (тестировщиков OSX сложно найти)?
Комментарии:
1. Происходит ли сбой с Clang libc и в Linux? Я подозреваю, что это так, как я наблюдал такое поведение в обсуждении для github.com/boostorg/function/pull/24 хотя , согласно boost.2283326.n4.nabble.com /… это должно было быть по-другому (
std::logic_error
не помечено как видимое в libstdc , но есть в libc ). В любом случае, Boost. ProgramOptions должны были быть исправлены 6 лет назад, когда svn.boost.org/trac10/ticket/10899 было сообщено, попробуйте отправить PR.2. В libc это тоже не удается. Похоже, причиной является изменение в libstdc , где он сравнивает искаженные имена типов вместо указателей typeinfo