Как запретить кому-либо красть мой shared_ptr? - PullRequest
7 голосов
/ 22 апреля 2010

Итак, я использую boost :: shared_ptr для всех различных преимуществ подсчета ссылок, которые он предоставляет - очевидно, для подсчета ссылок для начинающих, а также для возможности копирования, назначения и, следовательно, хранения в контейнерах STL.

Проблема в том, что, если я передам его только одной «вредоносной» функции или объекту, объект может сохранить ptr, и тогда я никогда не смогу отменить его выделение без посторонней функции или объекта, отказавшись от прав собственности. ,

В конечном счете, я стараюсь сохранить явное владение объектом. Я достигаю этого, когда владелец хранит только shared_ptr для объекта, а «гостевые» объекты хранят только weak_ptr для объекта.

Я действительно не хочу "разделяемую" часть shared_ptr, но мне нужно использовать shared_ptr для того, чтобы сделать weak_ptrs. Я хочу использовать scoped_ptr, но он крайне ограничен, поскольку вы не можете его скопировать. Вы не можете хранить его в контейнере, вы не можете выдавать слабые файлы из него и не можете передать право собственности новому менеджеру.

Какое решение?

Ответы [ 6 ]

10 голосов
/ 22 апреля 2010

Сделайте его приватным и предоставьте фасад для выполнения любых необходимых операций. Никто никогда не видит указатель. Я думаю, что в этот момент вам даже не понадобится shared_ptr.

4 голосов
/ 22 апреля 2010

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

1 голос
/ 22 апреля 2010

Достаточно использовать слабый_птр для гостевых объектов, как вы описали в вопросе.В противном случае у вас будут проблемы с мертвыми указателями.

Я бы подумал о том, чтобы перестроить приложение, чтобы удалить «вредоносные» функции / объекты или хотя бы исправить их поведение.

0 голосов
/ 22 апреля 2010

Если вы хотите обрабатывать свои объекты в этой парадигме владельца / владельца, я рекомендую сделать что-то вроде Qt.

  1. Создайте базовый класс Object, от которого будут наследоваться все классы в вашей системе.Каждый объект отслеживает своего родителя / владельца и потомков.
  2. Используйте метод setOwner(Object * owner), чтобы установить владельца, и пусть этот метод гарантирует, что объект владельца будет уведомлен о новом дочернем элементе.
  3. Деструктор для Object должен удалять все дочерние объекты при его разрушении.
  4. Определить шаблонный класс, который определяет умный указатель на подкласс Object.Сделайте так, чтобы Объект уведомлял любые подключенные умные указатели о своем уничтожении, чтобы при уничтожении объекта его значения становились НЕДЕЙСТВИТЕЛЬНЫМИ.

На что следует обратить внимание:

  1. Все объекты должны быть выделены через new для деструктора Objects, чтобы правильно их освободить.
  2. Если вы забыли установитьродитель для объекта, он утечет
  3. Обрабатывать объекты, которые не наследуются от Object, довольно сложно, хотя это можно сделать, определив класс-шаблон, который наследуется от Object для их хранения.
0 голосов
/ 22 апреля 2010

Нет действительно хорошего решения для того, что вы описываете.

Вы не можете использовать auto_ptr, потому что вы не передаете право собственности.

Если вы можете гарантировать, что владелец переживет ссылки, я бы рекомендовал использовать scoped_ptr / store по значению в владельце, а затем передать необработанный указатель или ссылку на тех, кто в этом нуждается.

Если ссылки могут пережить владельца (и ссылки должны быть изящно уведомлены), вы должны использовать shared_ptr / weak_ptr. Но, как вы заявили, вы не можете запретить ни одному классу / функции блокировать слабый_птр и «предотвращать» освобождение. Но, в интерфейсе, не передавайте shared_ptr, передайте слабый_птр. Он такой же сильный, как конвенция, но он говорит: «Не держись за это, он может уйти».

0 голосов
/ 22 апреля 2010

Вы можете расширить класс надстройки shared_ptr и переопределить удаление, чтобы принудительно удалить указатель.

На самом деле проблема в том, что если библиотека не освобождает или освобождает shared_ptr, то она, вероятно, будет ссылаться на нее некоторое время В это время ваше приложение упадет с SIGSEGV.

Я думаю, что это полностью отменяет цель общих указателей.

Лучшим решением является исправление библиотеки.

Другое решение, используйте AOP для удаления указателя при выходе из функции библиотеки, которую вы вызываете. Это все еще может сломаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...