Boost logo

Boost :

From: Alexander Grund (alexander.grund_at_[hidden])
Date: 2021-02-02 08:35:01


Hi Boost maintainers,

TLDR: Check your classes if they use BOOST_*_DECL and change that to
BOOST_SYMBOL_VISIBLE

In Boost.ProgramOptions I discovered an issue as a user, where I was
unable to catch an exception thrown from the shared Boost library in an
executable when both are build with hidden visibility.

It turns out the exception class was marked with
BOOST_PROGRAM_OPTIONS_DECL which evaluates to "visible" when building
the DLL but to nothing when using it.
This makes the linker (in theory) mark the typeinfo as hidden which
means that the class thrown by Boost and the one tried to catch are
unrelated.

See https://gcc.gnu.org/wiki/Visibility

> Symbol visibility is "default" by default but if the linker
encounters just one definition with it hidden - just one - that typeinfo
symbol becomes permanently hidden (remember the C++ standard's ODR - one
definition rule).

This is pretty clear that the current approach done by some Boost
libraries doesn't/shouldn't work and BOOST_SYMBOL_VISIBLE should be used
instead (or BOOST_SYMBOL_IMPORT should expand to BOOST_SYMBOL_VISIBLE.
This depends on how MSCV/Win32 platforms handle class visibility as on
Win32 BOOST_SYMBOL_VISIBLE expands to nothing. Maybe someone can clarify
here.)

As another datapoint:
https://github.com/boostorg/config/blob/5bcaa933b55dd58797775d87605a6cdef4acd5a2/doc/macro_reference.qbk
documents BOOST_SYMBOL_VISIBLE as the macro to be used for this.

Libraries which are (very likely) affected by this (quick grep) include:

Chrono
Container
Context
Contract
Coroutine
Fiber
Filesystem
IOStreams
JSON
Locale
MPI
ProgramOptions
Python
Regex
Test
Thread
Timer

Seemingly Linux platforms are less strict in actually enforcing this,
due to reason unknown to me. See my SO question:
https://stackoverflow.com/questions/65951466/why-can-a-thrown-exception-with-hidden-visibility-still-be-caught

Reason why this went undetected so far are the above (works on some
Linux, fails on e.g. OSX) and that user programs may often not be build
with hidden visibility AND rely on the exact same typeinfo from the
Boost library (most prominent: exceptions, dynamic_cast)

Regards,
Alex




Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk