Re: std::function and shared object libraries

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 13 June 2015 at 04:39, Gabriel Marcano <gabemarcano@xxxxxxxxx> wrote:
> I've been using std::function with GCC 5.1 in c++11 mode for registering some callbacks in a program. The program also loads in a shared library as a plugin, and is also allowed to register callbacks. Everything works as expected, but upon terminating the program segfaults. I traced the problem to the std::function destructor, which is using, in my case, an invalid _M_manager handle (which causes the segfault). Based on some further testing, it seems the handle is invalidated by the plugin being unloaded before the std::function destructor is called. If I switch the order of destruction/unloading, the program finishes without problems.
>
> I was able to reproduce the problem in a simple setup, which I'm inlining below. Simply run the Makefile, and then run the `test` executable. It should segfault (at least it does on my amd64 Linux system).
>
>
> Is std::function supposed to be that sensitive to shared libraries? Am I missing something from the documentation that explains this behavior? Thank you for any insight on the issue!

I don't see any way to avoid this, you're taking a pointer to code
defined in the shared library, then unloading the shared library, then
using the code that was just unloaded.

This isn't really a problem with std::function, it's just that
std::function makes it a bit easier to do, but your program is
equivalent to this:

// main.cpp

#include <dlfcn.h>

using f_t = void (*)();

extern "C" void load(f_t& fun);

int main()
{
  using sh_f = decltype(&load);
  void* lib = dlopen("./shared.so", RTLD_GLOBAL);
  sh_f sh = (sh_f)dlsym(lib, "load");
  f_t f;
  sh(f);
  dlclose(lib);
  f();
}


// shared.cpp

void shared() { }
using f_t = void (*)();

extern "C" void load(f_t& fun)
{
  fun = shared;
}

What happens in the std::function case is that the statement "fun =
shared;" instantiates a function template and stores a pointer to that
function in the fun._M_manager member. In the std::function destructor
that function is called. Boom.

There is no way for the C++ runtime to avoid this, because it has no
way of knowing a priori what types you are going to store in a
std::function, so it can't know which specializations of the function
template will be needed.





[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux