После появления умных указателей в стандартной библиотеке C++ проблема управления временем жизни объекта была решена.
Вы можете создавать объекты в стеке, а затем они будут автоматически удаляться, когда выходят за пределы области видимости, или использовать unique_ptr для создания объектов с монопольным владением илиshared_ptr для совместного владения.
Но только дляshared_ptr в стандартной библиотеке есть невладеющий указательweak_ptr, который предотвращает использование недопустимого указателя.
В других случаях используйте «старые и опасные» необработанные указатели.
Как разработчики языка предлагают решить эту проблему? На сайте Рекомендации CppCore есть несколько интересных документов( Здесь И Здесь ).
Основной посыл таков: мы не можем реализовать безопасные указатели, не являющиеся владельцами, не нарушая принцип нулевых накладных расходов.
Поэтому мы не будем реализовывать такие инструменты во время выполнения, а попробуем решить проблему путем статического анализа кода.
Я не согласен с этой позицией и вот мои причины:
- Статический анализ не сможет уловить все проблемы.
Сами авторы статей говорят, что иногда придется пометить некоторые проекты как безопасные, оставив вопрос корректности кода на совести разработчика.
- Чтобы статический анализ работал, необходима поддержка со стороны компиляторов.
Когда он появится, неизвестно.
- Статический анализ не позволяет иметь слабые указатели, не владеющие объектом (аналог слабого_ptr, который обнуляется при удалении объекта).
- Реализация таких указателей нарушает принцип нулевых накладных расходов — это правда.
Но, на мой взгляд, этот принцип нарушает и Shared_ptr, т. к.
имеет дополнительный объект ref_count или, например, строку с ее небольшой строковой оптимизацией.
В любом случае стандартная библиотека предоставляет классы с четко определенными характеристиками, а программист решает, подходят ему эти классы или нет.
Бесхозные указатели и доступ к висячим ссылкам — большая и до сих пор нерешенная тема в C++.
Я думаю, что стандартная библиотека должна предоставить программисту дополнительную возможность иметь такие указатели.
В вашем проекте РГБ Я попробовал реализовать такой указатель.
Основная идея не нова: нужен объект, который при уничтожении будет уведомлять указатели о факте удаления.
Таким образом, у нас есть два класса:
- rsl::track::отслеживаемый — класс, который уведомляет указатели при их удалении.
- rsl::track::указатель — фактический указатель, не являющийся владельцем.
Указатель на начало списка содержится в rsl::track::отслеживаемый .
Таким образом, создание указателей занимает постоянное время.
Размер р sl::track::отслеживаемый представляет собой один указатель, и rsl::track::указатель — 4 указателя (указатель на объект, два указателя для организации списка и еще один для реализации полиморфного поведения).
Возможно есть более оптимальная организация указателей, если кто знает, подскажите.
Кроме того, эта реализация не является потокобезопасной; для обеспечения работы в разных потоках придется добавить std::atomic_flag и замедлить модификацию указателей.
Более того, с появлением контейнеры с поддержкой распределителя , появилась возможность реализовать распределитель , что позволяет использовать rsl::track::указатель со стандартными контейнерами.
Основная идея заключается в том, что теперь все выделения в контейнерах выполняются экземпляром распределителя, хранящимся в контейнере, или его шаблонной копией, и мы можем хранить rsl::track::отслеживаемый в распределителе и передать его копиям.
В тесты приведены примеры работы с основными стандартными контейнерами, включая std::array, а также уникальный_ptr .
В заключение я хочу привести еще один сценарий, в котором rsl::track::указатель будет полезно.
Это ситуации похожие удалить это .
Обычно это происходит косвенно при вызове кода, функтора или внешнего по отношению к объекту сигнала.
Ошибки такого типа встречаются редко, но их трудно обнаружить.
Для таких случаев (и любых других проблем с доступом по висячей ссылке) используйте такие инструменты, как дезинфицирующие средства Google , которые позволяют выявлять такие проблемы.
Но у этих средств есть свои недостатки:
- Они работают не везде (не на всех платформах).
- Необходимо инструментирование кода — код отличается от производственного.
- Аналога слабого_ptr, указатель которого сбрасывается при удалении объекта, не существует.
- Определяет время и место доступа на основе недопустимого указателя.
Хотя, как правило, более интересный момент — это когда удаляется объект, на который есть указатели.
По этой же причине приборка выявляет не все случаи некорректного доступа, а только те, которые реально сработали при тестировании.
Возможно, есть и другие способы решения подобных проблем, буду рад услышать их в комментариях.
P.S. Еще раз для удобства привожу ссылку на код библиотеки РГБ .
Теги: #c++ #программирование #открытый исходный код #C++
-
Сравнение Wordpress, Joomla И Drupal
19 Oct, 24 -
Это Правильно, Но Это Неправильно
19 Oct, 24