Можно ли использовать boost :: shared ptr в интерфейсе DLL? - PullRequest
10 голосов
/ 24 декабря 2009

Допустимо ли разрабатывать DLL на C ++, которая возвращает общие указатели boost и использует их в качестве параметров?

Итак, можно ли экспортировать такие функции, как эта?

1.) boost::shared_ptr<Connection> startConnection();
2.) void sendToConnection(boost::shared_ptr<Connection> conn, byte* data, int len);

Специально: работает ли счетчик ссылок за пределами DLL, или требуется, чтобы exe и dll использовали одну и ту же среду выполнения?

Цель состоит в том, чтобы преодолеть проблемы с владением объектом. Таким образом, объект удаляется, когда dll и exe больше не ссылаются на него.

Ответы [ 5 ]

10 голосов
/ 10 ноября 2011

По словам Скотта Мейерса из Effective C ++ (3-е издание), shared_ptrs безопасны вне границ dll. Объект shared_ptr хранит указатель на деструктор из созданной им dll.

В своей книге в пункте 18 он заявляет: «Особенно приятная особенность tr1 :: shared_ptr заключается в том, что он автоматически использует свой указатель удаления чтобы устранить еще одну потенциальную ошибку клиента, «проблему кросс-DLL». Эта проблема возникает, когда объект создается с использованием нового в одном динамически связанная библиотека (DLL), но удаляется в другой библиотеке DLL. На на многих платформах такие кросс-DLL пары new / delete приводят к времени выполнения ошибки. tr1 :: shared_ptr избежать проблемы, потому что его по умолчанию удаления использует delete из той же DLL, в которой создан tr1 :: shared_ptr. "

У Тима Лешера есть интересное замечание, за которым он упоминает здесь . Вы должны убедиться, что DLL, которая создала shared_ptr, не выгружена, прежде чем shared_ptr наконец выйдет из области видимости. Я бы сказал, что в большинстве случаев это не то, за чем вам нужно следить, но если вы создаете dll, которые будут слабо связаны, то я бы рекомендовал не использовать shared_ptr.

Еще один потенциальный недостаток - создание обеих сторон совместимыми версиями библиотеки надстроек. Boost's shared_ptr долгое время оставался стабильным. По крайней мере, так как 1.34 он был совместим с tr1.

4 голосов
/ 24 декабря 2009

По моему мнению, если это не в стандарте и это не объект / механизм, предоставляемый вашей библиотекой, то он не должен быть частью интерфейса к библиотеке. Вы можете создать свой собственный объект для подсчета ссылок и, возможно, использовать boost под ним, но это не должно быть явно отображено в интерфейсе.

2 голосов
/ 05 января 2010

На что обратить внимание, если вы выставляете необработанные указатели из интерфейса dll. Это заставляет вас использовать разделяемую CRT DLL, память, выделенная в одной CRT, не может быть освобождена в другой CRT. Если вы используете общий dll CRT во всех своих модулях (dll's & exe's), то у вас все в порядке, все они используют одну и ту же кучу, если вы не пересекаете CRT, и мир рухнет.

Помимо этого вопроса, я согласен с принятым ответом. Фабрика создания, вероятно, не должна определять владение и управление жизненным циклом для клиентского кода.

2 голосов
/ 24 декабря 2009

DLL обычно не владеют ресурсами - ресурсы принадлежат процессам, которые используют DLL. Вам, вероятно, лучше вернуть простой указатель, который вы затем сохраните в общем указателе на вызывающей стороне. Но без дополнительной информации трудно быть на 100% уверенным в этом.

0 голосов
/ 08 августа 2014

Нет, это не так.

Расположение boost::shared_ptr<T> может не совпадать с обеих сторон границы DLL. (На макет влияют версия компилятора, прагмы упаковки и другие параметры компилятора, а также текущая версия исходного кода Boost.)

Только "стандартные макеты" (новая концепция в C ++ 11, связанная со старой концепцией "POD = обычные старые данные") могут безопасно передаваться между отдельно построенными модулями.

...