Почему выброшенное исключение со скрытой видимостью все еще может быть перехвачено

#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