ПК>Для возвращаемого значения или других случаев, где нужно подчеркнуть передачу владения -- auto_ptr, для объекта, который никуда из данной области видимости "уплыть не должен" -- scoped_ptr, для объекта с разделяемым владением -- shared_ptr, для не владеющих ссылок на него -- weak_ptr и т.п. Если объект нельзя удалять "обычным" delete, жизнь в этом контексте становится сложнее.
Смею заметить, автопоинтер — сам по себе тоже объект
Здравствуйте, Аноним, Вы писали:
ПК>>Для возвращаемого значения или других случаев, где нужно подчеркнуть передачу владения -- auto_ptr, для объекта, который никуда из данной области видимости "уплыть не должен" -- scoped_ptr, для объекта с разделяемым владением -- shared_ptr, для не владеющих ссылок на него -- weak_ptr и т.п. Если объект нельзя удалять "обычным" delete, жизнь в этом контексте становится сложнее.
А>Смею заметить, автопоинтер — сам по себе тоже объект
Гм... Не вполне понял, к чему это... Можно мысль поподробней развернуть?
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[9]: delete this
От:
Аноним
Дата:
09.04.07 13:39
Оценка:
А>>Смею заметить, автопоинтер — сам по себе тоже объект ПК>Гм... Не вполне понял, к чему это... Можно мысль поподробней развернуть?
Если функция вернет автопоинтер на объект, кто вызовет деструктор самого автопоинтера? От этого зависит то, кто вызовет delete на указатель внутренние структуры автопоинтера и на сам объект который внутри хранится.
Если уж юзать автопоинтеры то экспортируемая dll функция должна возвращать простой указатель на объект с Release()'ом, а вызывающий должен заключать этот полученный указатель в свой автопоинтер который в конце вызовет не delete на объект, а Release. Как это и делает микрософтовский _com_ptr_t.
Кстати такой автопоинтер изобретать не надо — такое легко сделать и при помощи бустовского shared_ptr.
Здравствуйте, Аноним, Вы писали:
А>>>Смею заметить, автопоинтер — сам по себе тоже объект ПК>>Гм... Не вполне понял, к чему это... Можно мысль поподробней развернуть? А>Если функция вернет автопоинтер на объект, кто вызовет деструктор самого автопоинтера? От этого зависит то, кто вызовет delete на указатель внутренние структуры автопоинтера и на сам объект который внутри хранится.
В shared_ptr этой проблемы нет. Из какой бы dll не вызвали деструктор shared_ptr его объект и счетчик удалятся корректно.
С уважением, Александр
Re[11]: delete this
От:
Аноним
Дата:
09.04.07 14:38
Оценка:
S>В shared_ptr этой проблемы нет. Из какой бы dll не вызвали деструктор shared_ptr его объект и счетчик удалятся корректно.
1) Покажите пожалуйста место где это написано в документации по boost::shared_ptr?
2) Из какого фрагмента кода shared_ptr.hpp это следует?
Здравствуйте, Аноним, Вы писали:
S>>В shared_ptr этой проблемы нет. Из какой бы dll не вызвали деструктор shared_ptr его объект и счетчик удалятся корректно.
А>1) Покажите пожалуйста место где это написано в документации по boost::shared_ptr? А>2) Из какого фрагмента кода shared_ptr.hpp это следует?
shared_ptr::pn::get_deleter(), виртуальная функция удалает тем delete каким был создан (хитро там намешано )
Не стыдно попасть в дерьмо, стыдно в нём остаться!
Re[13]: delete this
От:
Аноним
Дата:
09.04.07 14:59
Оценка:
D>shared_ptr::pn::get_deleter(), виртуальная функция удалает тем delete каким был создан (хитро там намешано )
Хм ну если так то тогда мона юзать shared_ptr
Но я всегда юзаю нормальный Release для инетрфейсов по одной можно сказать идеологической причине.
Интерфейс — это полностью абстрактный класс в котором не реализован ни один метод. Объявляя
class IBaseClass
{
public:
virtual ~IBaseClass(){};
};
Вы создаете класс с реализованным деструктором. То бишь нифига он уже не абстрактный. Кроме того этот деструктор очень сильно ограничивает выбор компиляторов которыми компиляются разные модули. Например VS/Делфи для разнгых модулей заюзать не получится. Да и сама микрософт неспроста пошла по пути virtual void Release() в своих комах.
Здравствуйте, Аноним, Вы писали:
S>>В shared_ptr этой проблемы нет. Из какой бы dll не вызвали деструктор shared_ptr его объект и счетчик удалятся корректно.
А>1) Покажите пожалуйста место где это написано в документации по boost::shared_ptr?
Это следует из следующего абзаца (хотя, возможно есть более точное упоминание)
Custom deallocators allow a factory function returning a shared_ptr to insulate the user from its memory allocation strategy. Since the deallocator is not part of the type, changing the allocation strategy does not break source or binary compatibility, and does not require a client recompilation. For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object, and other variations allow a shared_ptr to be used as a wrapper for another smart pointer, easing interoperability.
(отсюда)
А>2) Из какого фрагмента кода shared_ptr.hpp это следует?
А по коду тоже можно посмотреть.
shared_ptr держит указателя на объект и класс-обёртку для счетчика (detail::shared_count).
detail::shared_count выделяет динамически память для счетчика и deleter-а (sp_counted_impl_p/sp_counted_impl_pd).
У sp_counted_impl_p/sp_counted_impl_pd есть виртуальный метод dispose (унаследованный от sp_counted_base),
который вызывает deleter для хранимого указателя. Т.к. все это скрыто за виртуальным указателем, то удаляется в dll,
которая выделила память (даже в случае, если deleter стандартный и просто вызывается boost::checked_delete(p)).
Сам sp_counted_impl_p/sp_counted_impl_pd удаляется через виртуальный метод destroy (делается delete this).
Так что все безопасно.
С уважением, Александр
Re[13]: delete this
От:
Аноним
Дата:
09.04.07 15:04
Оценка:
Ok, а как насчет случая когда модуля окажутся скомпиленными разными версиями буста у которого чтото изменилось со струкурой shared_ptr?
Здравствуйте, Аноним, Вы писали:
D>>shared_ptr::pn::get_deleter(), виртуальная функция удалает тем delete каким был создан (хитро там намешано ) А>Хм ну если так то тогда мона юзать shared_ptr А>Но я всегда юзаю нормальный Release для инетрфейсов по одной можно сказать идеологической причине. А>Интерфейс — это полностью абстрактный класс в котором не реализован ни один метод. Объявляя
class IBaseClass
{
public:
virtual ~IBaseClass() =0 {};
};
Здравствуйте, Аноним, Вы писали:
А>Ok, а как насчет случая когда модуля окажутся скомпиленными разными версиями буста у которого чтото изменилось со струкурой shared_ptr?
Да врядли что-то там в виртуальном интерфейсе изменится. Поэтому, все будет пучком.
Здравствуйте, Аноним, Вы писали:
А>>>Смею заметить, автопоинтер — сам по себе тоже объект
ПК>>Гм... Не вполне понял, к чему это... Можно мысль поподробней развернуть?
А>Если функция вернет автопоинтер на объект, кто вызовет деструктор самого автопоинтера?
Допустим, вызывающий код в другом модуле (иначе ситуация, вообще, неинтересная).
А>От этого зависит то, кто вызовет delete на указатель внутренние структуры автопоинтера
Либо у "умного" указателя нет никаких внутренних структур, требующих delete (scoped_ptr, auto_ptr), либо об этом позаботились авторы "умного" указателя (shared_ptr, weak_ptr).
А>и на сам объект который внутри хранится.
В случае экспортируемого перегруженного delete для объекта это не имеет значения, т.к. вне зависимости от местонахождения кода, вызывающего delete, должен быть использован экспортированный вариант.
А>Если уж юзать автопоинтеры то экспортируемая dll функция должна возвращать простой указатель на объект с Release()'ом, а вызывающий должен заключать этот полученный указатель в свой автопоинтер который в конце вызовет не delete на объект, а Release. Как это и делает микрософтовский _com_ptr_t.
Это совершенно другой use case. Там нужна возможность работы не только через границу модулей, но и с модулями, построенными несовместимыми компиляторами и даже написанными на других языках. Привносить все эти сложности, теряя в выразительности интерфейсов, в случае "нормальных", "монокомпиляторных" DLL я не вижу никакого смысла.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Я не знаю что говорит стандарт по этому поводу, но знаю что MS пошел по второму пути.
И по этой причине первый тест прошел на ура. Т.е. используется правильный менеджер памяти (CRT library)
Что касается второго вашего теста, смесь разных компиляторов, то в этом случае можно говорить только об экспорте/импортирте интерфейсов. Т.к. экспорт/импорт классов (реализаций) это сугубо компиляторно зависимая вешь (декорация имен и т.д. и т.п.).
Вывод:
Виртуальный деструктор решает проблему использования нужного CRT при разрушении объекта. Но надо понимать, что в этом случае речь идет не об экспорте интерфейса а об экспорте класса. А это уже совсем другая песня, и проблема с освобождением объекта покажется цветочками.
Re[18]: delete this
От:
Аноним
Дата:
10.04.07 09:01
Оценка:
K>Теперь рассмотрим методы реализации:
Не надо смотреть методы реализации, если только вы не пишете свою реализацию. В остальных случаях надо читать документацию.
Таким образом тест доказал что я прав ? Вы мой вариант теста запусти , поняли о чем речь идет ?
А то что не работает с борманом и почему это отдельная история, надо в отладку идти.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[18]: delete this
От:
Аноним
Дата:
10.04.07 12:59
Оценка:
M>Таким образом тест доказал что я прав ? Вы мой вариант теста запусти , поняли о чем речь идет ?
Речь идет о написании C++ — compliant кода, а не MSVC X on Windows Y — compliant
M>А то что не работает с борманом и почему это отдельная история, надо в отладку идти.
Не работает — значит не совместимо со всеми С++ компилерами.
Здравствуйте, Аноним, Вы писали:
M>>Таким образом тест доказал что я прав ? Вы мой вариант теста запусти , поняли о чем речь идет ? А>Речь идет о написании C++ — compliant кода, а не MSVC X on Windows Y — compliant
Вы поставили довольно четкую проблему (а именно удаление памяти соответствующим менеджером памяти). Я написал как ее решить, С++ СОВМЕСТИМО. Написал тест демонстрирующий мои тезисы. Запустите его на той платформе где хотите совместимости.
M>>А то что не работает с борманом и почему это отдельная история, надо в отладку идти. А>Не работает — значит не совместимо со всеми С++ компилерами.
Еще раз повторяю, тот баг который вы обнаруживаете, скорее всего не связан с описанной проблемой и требует отдельного изучения.
M>>>Таким образом тест доказал что я прав ? Вы мой вариант теста запусти , поняли о чем речь идет ? А>>Речь идет о написании C++ — compliant кода, а не MSVC X on Windows Y — compliant
M>Вы поставили довольно четкую проблему (а именно удаление памяти соответствующим менеджером памяти). Я написал как ее решить, С++ СОВМЕСТИМО.
Вы написали как ее решить MSVC++ совместимо.
M>Написал тест демонстрирующий мои тезисы. Запустите его на той платформе где хотите совместимости.
Я запустил. Win/Builder C++ — а delete упало. virtual void Release(){delete this;} работает на ура. Тот же код MSVC работает в обоих случаях.
M>>>А то что не работает с борманом и почему это отдельная история, надо в отладку идти. А>>Не работает — значит не совместимо со всеми С++ компилерами. M>Еще раз повторяю, тот баг который вы обнаруживаете, скорее всего не связан с описанной проблемой и требует отдельного изучения.
Если такое решение требует отдельного изучения реализации таблицы виртуальных методов в каждом из компиляторов — извольте. Мне нужен С++ решение. А межде прочим способ реализации виртуальных методов (структура vtbl и прочее) стандартом С++ никак не определяется, потому любое решение основывющееся на этом — грязный хак.