Можно ли использовать boost::shared ptr в интерфейсе DLL?
-
21-09-2019 - |
Вопрос
Допустимо ли разработать DLL на C++, которая возвращает общие указатели повышения и использует их в качестве параметров?
Итак, можно ли экспортировать подобные функции?
1.) boost::shared_ptr<Connection> startConnection();
2.) void sendToConnection(boost::shared_ptr<Connection> conn, byte* data, int len);
В особенности:Работает ли подсчет ссылок за пределами границ DLL или требуется, чтобы exe и dll использовали одну и ту же среду выполнения?
Цель состоит в том, чтобы преодолеть проблемы с владением объектом.Таким образом, объект удаляется, когда dll и exe больше не ссылаются на него.
Решение
По словам Скотта Мейерса в «Эффективном C++» (3-е издание), «shared_ptrs» безопасны за пределами границ dll.Объектshared_ptr хранит указатель на деструктор из dll, которая его создала.
В своей книге в пункте 18 он заявляет: «Особенно хорошая особенность tr1 :: shared_ptr заключается в том, что он автоматически использует свой Deleorter для устранения еще одной потенциальной ошибки клиента,« Проблема Cross-DLL ». Эта проблема возникает, когда Объект создается с использованием новой в одной динамически связанной библиотеке (DLL), но удаляется в другой DLL.На многих платформах такие новые/удаленные пары Cross-Dll приводят к ошибкам времени выполнения.tr1 :: shared_ptr Избегайте проблемы, потому что его Daleter использует Delete из того же DLL, где создается tr1 :: shared_ptr ».
Однако у Тима Лешера есть интересная особенность, о которой он упоминает. здесь.Вам необходимо убедиться, что DLL, создавшая общий_ptr, не выгружена до того, как общий_ptr окончательно выйдет из области действия.Я бы сказал, что в большинстве случаев на это не стоит обращать внимание, но если вы создаете слабосвязанные библиотеки DLL, я бы рекомендовал не использоватьshared_ptr.
Еще одним потенциальным недостатком является необходимость создания обеих сторон с использованием совместимых версий библиотеки boost.Shared_ptr Boost уже долгое время работает стабильно.По крайней мере с тех пор 1.34 он совместим с tr1.
Другие советы
По моему мнению, если этого нет в стандарте и не является объектом/механизмом, предоставляемым вашей библиотекой, то он не должен быть частью интерфейса библиотеки.Вы можете создать свой собственный объект для подсчета ссылок и, возможно, использовать boost, но он не должен быть явно представлен в интерфейсе.
Библиотеки DLL обычно не владеют ресурсами — ресурсы принадлежат процессам, использующим DLL.Вероятно, вам лучше вернуть простой указатель, который затем сохраните в общем указателе на вызывающей стороне.Но без дополнительной информации трудно быть уверенным в этом на 100%.
На что следует обратить внимание, если вы предоставляете необработанные указатели из интерфейса dll.Это заставляет вас использовать общую dll CRT, память, выделенная в одном CRT, не может быть освобождена в другом CRT.Если вы используете общую dll CRT во всех своих модулях (dll и exe), тогда все в порядке, все они используют одну и ту же кучу, если вы этого не сделаете, вы пересечете CRT, и мир рухнет.
Помимо этого вопроса, я согласен с принятым ответом.Фабрика создания, вероятно, не должна определять владение и управление жизненным циклом клиентского кода.
Нет это не так.
Расположение boost::shared_ptr<T>
может быть разным по обе стороны границы DLL.(На макет влияет версия компилятора, директивы упаковки и другие параметры компилятора, а также фактическая версия исходного кода Boost.)
Только типы «стандартного макета» (новая концепция в C++11, связанная со старой концепцией «POD = простые старые данные») могут безопасно передаваться между отдельно созданными модулями.