Возвращение unique_ptr из функции, выполняемой через dlsym - PullRequest
0 голосов
/ 09 июля 2019

У меня есть функция, которая находится в общем объекте, загружается и выполняется с dlsym из основной программы.(и общий объект, и основная программа - C ++)

Возможно ли, что эта функция возвратит std::unique_ptr?

функция общего объекта -

extern "C" {
    unique_ptr<Obj> some_function() {
        return make_unique<Obj>();
    }
}

mainпрограмма:

void main_flow() {
    auto handle = dlopen(...);
    FuncPtr func = dlsym(handle, "some_function");
    unique_ptr<Obj> func();
}

1 Ответ

1 голос
/ 09 июля 2019

Да, с большим количеством оговорок. Во-первых, использование boost или STL в интерфейсе DSO немного опасно.

  1. std :: unique_ptr отличается между компиляторами
  2. std :: unique_ptr отличается между версиями C ++
  3. std :: unique_ptr может отличаться в зависимости от сборки отладки / выпуска.

Это означает, что если вы используете STL или boost в своем интерфейсе DSO, ВСЕ exes и dsos должны использовать одну и ту же версию среды выполнения C ++, скомпилированную с теми же флагами сборки (и той же версией boost, если вы в этом разбираетесь).

Я бы рекомендовал использовать уровень предупреждения 4 в Visual Studio, в котором будут перечислены все вышеупомянутые проблемы в ваших интерфейсах DSO (как предупреждения C4251)

Что касается вашего вопроса, то да, функция вернет std :: unique_ptr, однако вы сейчас выделяете память в DSO, которую вы, возможно, освобождаете в exe. Это может быть очень плохо в мире Windows, где вы можете обнаружить, что отладочные сборки имеют разные кучи. Попытка освободить выделенный DSO-объект в куче EXE вызовет ошибку времени выполнения, но обычно только в отладочных сборках.

Ваш главный должен выглядеть так:

void main_flow() {
  auto handle = dlopen(...);
  FuncPtr func = (FuncPtr)dlsym(handle, "some_function");
  unique_ptr<Obj> obj = func();
}  

Лично я бы порекомендовал просто вернуть голый указатель и выполнить make_unique для него в вашем exe-файле. Это, по крайней мере, устраняет проблемы C4251, хотя вы можете быть укушены проблемой кучи (если вы не сделаете деструктор типа класса виртуальным)

...