Можно ли использовать boost:: shared ptr в DLL-интерфейсе?

Можно ли разработать DLL на С++, который возвращает форсированные общие указатели и использует их как параметры?

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

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

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

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

Ответ 1

Согласно Scott Meyers в Effective С++ (3rd Edition), shared_ptrs безопасны для границ dll. Объект shared_ptr хранит указатель на деструктор из DLL, которая его создала.

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

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

Другим потенциальным недостатком является то, что обе стороны создаются с совместимыми версиями библиотеки boost. Boost shared_ptr долгое время стабилизировался. По крайней мере, поскольку 1.34, он был совместим с tr1.

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

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