кстати safe_ptr не поддерживают указатели на вложенные объекты (например shared_ptr может), это еще одна причина, почему он такой простой. ну и поддержки многопоточности нет, как и у меня.
Люди склонны ошибаться. В любом случае, мы переходим в область субъективных суждений: вряд ли, существует статистика как часто такие ошибки допускают. Могу снова предложить почитать статьи авторов PVS Studio и сделать поправку на то, что им попадает в руки код после ревью, прохождения тестов, а бывает, что и после других анализаторов.
Соглашусь. Rust в этом смысле шаг вперед. Особенно если посмотреть на историю его создания.
И да, всё что делает раст — «встраивает» некоторые проверки в сам язык без необходимости подключать тяжёлую артиллерию в виде статических анализаторов и валгринда (и да, я в курсе, что эти инструменты могут быть полезны и в расте).
Может языку С++ стоит идти в эту же сторону, но с другой стороны — вставлять куски кода помеченные как safe, где будут работать строгие проверки как в Rust. И мы в своем коде будем понемногу расширять область safe: о)
смотрю на safe_ptr.
да, прям мои мысли, когда я начинал писать свой веловипед. Потом захотелось прикрутить стандартные контейнеры и пришлось всё усложнить. Спасибо за ссылку.
ловить то надо факт лочки мёртвого shared_ptr
гораздо интересенее момент разрушения объекта, на который есть ссылки.
А для релиза достаточно счётчика ссылок и проверки, что при разрушении trackable счётчик равен нулю. Оповещать указатели о том, что объект сдох — бессмысленно.
согласен, но у меня не получилось прикрутить такой простой указатель к стандартным контейнерам. когда на все элементы контейнера один trackable в аллокаторе. Может есть мысли как это можно улучшить?
это не использовать «голые» указатели в коде вообще.
Так вот нет невладеющих смарт указателей в стандарте (есть попытка observer_ptr).
owner и not_null хороши, но мне кажется not_null это полиси к любому другому указателю, а не отдельный тип.
чтобы можно было иметь owner_not_null, unique_ptr_not_null, shared_ptr_not_null и т.п.
По такому же принципу можно добавить класс scoped_pointer, который будет гарантировать, что любая его копия умрёт раньше, чем указатель, из которого она создана и которым «временно владеет».
очень интересная задачка. есть мысли как можно реализовать эти гарантии? запретить копирование/перемещение?
если же вас интересует функциональность, то shared_ptr и weak_ptr обладают нужной функциональностью (по крайней мере я не видел, чтобы кто-то показал обратное)
Как я писал в статье, для отлова ошибок, гораздо интереснее момент, когда разрушается объект, на который есть ссылки, а не когда пытаются обратится по невалидному указателю. В этом случае shared_ptr/weak_ptr никак не помогут.
не значит, что мы не можем использовать shared_ptr/weak_ptr для отлова ошибок в коде
Мы не можем просто взять и добавить в существующий код shared_ptr, потому что если ваши объекты лежат на стеке или в unique_ptr или еще где-то, то нельзя их привязать к shared_ptr.
Вернее можно, указав пустой deleter, но смысла в этом нет. Так как weak_ptr отловят окончание использования shared_ptr'ов, а не разрушение объекта.
Вы предлагаете отлавливать dangling pointers — это это ошибочная ситуация, weak_ptr и shared_ptr позволяют ее отловить и являются стандартным средством языка.
Я как раз думаю иначе.
В стандарте нет средств отлова висячих ссылок, эту проблему хотят частично решать статическим анализом. Мне это не совсем нравится, думаю нужно так же runtime решение. Например такое, как у меня.
Так что сравнение как раз таки имеет смысл.
Ну если очень хочется, давайте сравним.
1. Конструирование объекта: shared_ptr — аллокация; track::trackable — ничего.
2. Создание новоро указателя: shared_ptr — инкремент, track::pointer — четыре присваивания указателей.
3. Удаление указателя: shared_ptr — декремент, track::pointer — четыре присваивания указателей.
4. Удаление объекта: shared_ptr — декремент, weak_ptr — деаллокация; track::pointer — проход по списку указателей с вызовом функции on_dangle.
Как указали выше или вот тут, некоторые люди, и я в их числе, не считаем, что shared_ptr каким-то образом предназначены для решения проблем висячих ссылок. Могу если надо найти презентацию Герба с табличкой, в которой перечисленны ситуации и указатели, которые нужно при этом использовать.
Скажите как специалист по Rust, как на нем писать ГУИ. Например, по каким-то событиям удалять часть окон и создавать другие?
И смогу ли я в таком случае случайно удалить кнопку, которая сейчас как раз и рассылает событие клик?
С этим трудно спорить — светлая голова лучше тёмной: о).
Но светлая голова не панацея. На любого гения найдется такой сложности проект, который окажется ему не под силу. Здесь главное, какие мы даем инструменты, помогающие ему управлять сложностью или выявлять проблемы как можно раньше.
Все мы крепки задним умом, но иногда система, которую мы программируем ведет себя не так как ожидается. Это нормально, в том смысле, что так было, есть и будет. И здесь при прочих равных на первый план выходит качество и мощь как раз инструментов, которыми обладает программист.
В статье описан, как раз один такой инструмент, со своими достоинствами и недостатками. мне кажется баланс достоинств и недостатков вполне приемлем: о)
С ним другие проблемы, написал об этом в комментарии ниже.
Вообще у любого решения есть проблемы и нюансы, в моем они так же присутствуют. От этого никуда не деться. Вопрос лишь баланса ценности и стоимости того или другого интструмента.
Ловить можно с помощью таких утилит, как MemorySanitizer, valgrind, Dr.Memory и прочих.
Про них я упомянул в статье со списком недостатков, по моему мнению.
И просто взять за правило, что нельзя удалять объект, а потом к нему обращаться.
Это хорошое правило и самоочевидное правило. Так же можно посоветовать соблюдать ПДД чтобы никогда не попадать в аварии. Но мы то знаем, что жизнь сложнее и соблюдение правил не залог безопасности. Снизить вероятность можно, полностью исключить проблем — нельзя.
deleteLater — не GC.
Ну почему же, можно на него посмотреть с этой точки зрения. Вместо удаления объектов, которые нам не нужны, мы помечаем их как неиспользуемые и оставляем в памяти. Ни о каком RAII при этом речь уже идти не может (что также верно и для Java/C#).
Вы точно знаете, когда объект будет удалён — при следующем цикле обработчика событий.
Это половина правды: о). Согласно докам, объект, переданный в deleteLater может быть вообще никогда не удален.
К тому же непонятно что будет если передать туда объект не созданный в куче? Лучше так не делать, это понятно, но как отличить если к вам в функцию пришел указатель на объект и непонятно надо/можно его удалять через deleteLater или нет.
На самом деле я не сильно критикую deleteLater — это хороший инструмент по быстрому исправлению проблем, не более того. Вполне удобное компромиссное решение, по сути костыль, за не имением более достойного варианта.
Тут соглашусь…
после стольких лет топтания на месте язык С++ переживает ренесанс и у многих зачесались ручки добавить в язык кучу «классных» штучек. Меня особо смущает proposal на 2D drawing на основе С библиотеке Cairo.
Но проблема висячих ссылок универсальная, недаром над ней сейчас активно работают и Бьярне и Герб (см. ссылки в статье). Только вот не давать run-time иструмент для решения, а пытаться частично решить с помощью статического анализа, мне кажется в корне не верна. О чем собственно и статья.
Соглашусь. Rust в этом смысле шаг вперед. Особенно если посмотреть на историю его создания.
Может языку С++ стоит идти в эту же сторону, но с другой стороны — вставлять куски кода помеченные как safe, где будут работать строгие проверки как в Rust. И мы в своем коде будем понемногу расширять область safe: о)
На что был ответ — не всегда пожно перейти на Rust, поэтому комментарий про Rust вообще не в тему.
да, прям мои мысли, когда я начинал писать свой веловипед. Потом захотелось прикрутить стандартные контейнеры и пришлось всё усложнить. Спасибо за ссылку.
гораздо интересенее момент разрушения объекта, на который есть ссылки.
согласен, но у меня не получилось прикрутить такой простой указатель к стандартным контейнерам. когда на все элементы контейнера один trackable в аллокаторе. Может есть мысли как это можно улучшить?
Так вот нет невладеющих смарт указателей в стандарте (есть попытка observer_ptr).
owner и not_null хороши, но мне кажется not_null это полиси к любому другому указателю, а не отдельный тип.
чтобы можно было иметь owner_not_null, unique_ptr_not_null, shared_ptr_not_null и т.п.
очень интересная задачка. есть мысли как можно реализовать эти гарантии? запретить копирование/перемещение?
как советуют выше — везде светлая голова нужна
Как я писал в статье, для отлова ошибок, гораздо интереснее момент, когда разрушается объект, на который есть ссылки, а не когда пытаются обратится по невалидному указателю. В этом случае shared_ptr/weak_ptr никак не помогут.
Мы не можем просто взять и добавить в существующий код shared_ptr, потому что если ваши объекты лежат на стеке или в unique_ptr или еще где-то, то нельзя их привязать к shared_ptr.
Вернее можно, указав пустой deleter, но смысла в этом нет. Так как weak_ptr отловят окончание использования shared_ptr'ов, а не разрушение объекта.
Я как раз думаю иначе.
В стандарте нет средств отлова висячих ссылок, эту проблему хотят частично решать статическим анализом. Мне это не совсем нравится, думаю нужно так же runtime решение. Например такое, как у меня.
Ну если очень хочется, давайте сравним.
1. Конструирование объекта: shared_ptr — аллокация; track::trackable — ничего.
2. Создание новоро указателя: shared_ptr — инкремент, track::pointer — четыре присваивания указателей.
3. Удаление указателя: shared_ptr — декремент, track::pointer — четыре присваивания указателей.
4. Удаление объекта: shared_ptr — декремент, weak_ptr — деаллокация; track::pointer — проход по списку указателей с вызовом функции on_dangle.
Вроде так.
Так что боюсь само сравнение не имеет смысла.
И смогу ли я в таком случае случайно удалить кнопку, которая сейчас как раз и рассылает событие клик?
Но светлая голова не панацея. На любого гения найдется такой сложности проект, который окажется ему не под силу. Здесь главное, какие мы даем инструменты, помогающие ему управлять сложностью или выявлять проблемы как можно раньше.
Все мы крепки задним умом, но иногда система, которую мы программируем ведет себя не так как ожидается. Это нормально, в том смысле, что так было, есть и будет. И здесь при прочих равных на первый план выходит качество и мощь как раз инструментов, которыми обладает программист.
В статье описан, как раз один такой инструмент, со своими достоинствами и недостатками. мне кажется баланс достоинств и недостатков вполне приемлем: о)
Вообще у любого решения есть проблемы и нюансы, в моем они так же присутствуют. От этого никуда не деться. Вопрос лишь баланса ценности и стоимости того или другого интструмента.
Про них я упомянул в статье со списком недостатков, по моему мнению.
Это хорошое правило и самоочевидное правило. Так же можно посоветовать соблюдать ПДД чтобы никогда не попадать в аварии. Но мы то знаем, что жизнь сложнее и соблюдение правил не залог безопасности. Снизить вероятность можно, полностью исключить проблем — нельзя.
Ну почему же, можно на него посмотреть с этой точки зрения. Вместо удаления объектов, которые нам не нужны, мы помечаем их как неиспользуемые и оставляем в памяти. Ни о каком RAII при этом речь уже идти не может (что также верно и для Java/C#).
Это половина правды: о). Согласно докам, объект, переданный в deleteLater может быть вообще никогда не удален.
К тому же непонятно что будет если передать туда объект не созданный в куче? Лучше так не делать, это понятно, но как отличить если к вам в функцию пришел указатель на объект и непонятно надо/можно его удалять через deleteLater или нет.
На самом деле я не сильно критикую deleteLater — это хороший инструмент по быстрому исправлению проблем, не более того. Вполне удобное компромиссное решение, по сути костыль, за не имением более достойного варианта.
Посоветуйте Линусу слезть с С и переползать на Golang или Rust. Думаю узнаете много идиоматических финских слов: о) (шутка).
В общем-то, поддерживать старые проекты и плавно переводить их на новые плюшки языка — вполне себе выход во многих случаях.
Вот здесь не уловил.
после стольких лет топтания на месте язык С++ переживает ренесанс и у многих зачесались ручки добавить в язык кучу «классных» штучек. Меня особо смущает proposal на 2D drawing на основе С библиотеке Cairo.
Но проблема висячих ссылок универсальная, недаром над ней сейчас активно работают и Бьярне и Герб (см. ссылки в статье). Только вот не давать run-time иструмент для решения, а пытаться частично решить с помощью статического анализа, мне кажется в корне не верна. О чем собственно и статья.
И как раст помогает в этих случаях?
Там черным по белому написано, что иногда Rust слишком консервативен и не позволит скомпилировать код, не поддающийся валидации.
Дело в том, что в С++ сейчас проблема висячих ссылок попадается тоже очень редко. И нет инструмента по по отлову таких случаев.
Уверен в Rust тоже редко возникают «мутные» места, которые нужно оборачивать в unsafe.
И здесь Rust программисту ничем не помогает.