Boost logo

Boost Users :

Subject: Re: [Boost-users] double free when both shared library and executable linked to boost libraries
From: Eric Roller (eroller_at_[hidden])
Date: 2015-01-08 15:51:42


On Tue, Jan 6, 2015 at 12:55 AM, John Maddock <boost.regex_at_[hidden]> wrote:
>>> So you can see, only when the main executable used static linking to
>>> boost and the shared library used dynamic linking to boost is when I
>>> saw the double free error at run time. My question is, why is the
>>> error only triggered under that condition and what is the recommended
>>> link configuration when using boost libraries for both a shared
>>> library and an executable.
>>>
>>> Ideally, the shared library plug-in should be free to use any boost
>>> version with either static or dynamic linking, and it should be
>>> independent from (i.e. not conflict with) the main executable's boost
>>> version and link type. What compiler/link settings would be necessary
>>> to achieve this, if it is even possible at all?
>>
>>
>> Provided that Boost objects appear *nowhere* in the ABI of your library
>> (safest is to ensure that none of your public header files ever #include
>> or forward-reference anything from Boost), you should be safe
>> static-linking on both sides, or even mixing things up like above.
>>
>> If Boost objects do appear in the ABI of your library, then you have to
>> be more careful. The safest option is to dynamic link on both sides.
>> (You may sometimes be able to get away with static linking on both sides
>> depending on which libraries you're using, particularly when they're
>> header-only, but it's still not a good idea.)
>
>
> I meant to reply to this and forgot :-(
>
> You don't say which Boost lib is causing the issue, but my guess it goes
> something like this:
>
> * You're using Boost.Regex (or a similar lib which frees resources on exit).
> * When the pluggin is loaded, the link-loader resolves dependencies by using
> the static version of the lib already present in the executable rather than
> by loading the shared lib.
> * When the pluggin is unloaded, it prematurely calls the libraries cleanup
> routines.
> * When the application exits, it calls the same routines again.
>
> As Gavin says, there's only one safe option and that's either all-dynamic or
> all static linking, mixing the two is a recipe for problems like this - not
> just with Boost, but with any third party library. I guess the problem is
> that you don't have control over the pluggin?
>
> There may be one other option - assuming this is Linux/GCC you could,
> perhaps even *should* make all third party library symbols private by
> compiling with -fvisibility=hidden. In fact if one or more Boost libraries
> are not doing this anyway for the static lib builds, please file a bug
> report!

Thanks for your responses, they are very helpful.

Unfortunately I was not able to pinpoint the specific boost library
that caused the double free using address sanitizer. As you mentioned
the double free occurs during program exit routine and all I see is
that some std::string object is being freed.

In this case I do have access to both the main executable and the
plugins so I can choose how they are compiled to avoid this error. It
would still be good to figure out how I can compile the main
executable to be robust to how the shared library plugins are
compiled. I will try compiling boost with hidden visibility to see if
it resolves this issue. Is this the correct way to achieve that?:

./b2 link=static threading=multi cxxflags='-fPIC -fvisibility=hidden
-fvisibility-inlines-hidden' install

Aren't there some boost libraries that force symbols to have default
visibility? If so, setting -fvisibility=hidden won't change that.

-Eric


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net