Страницы

Поиск по вопросам

воскресенье, 26 января 2020 г.

operator new

#cpp


Вот такой вопрос для любителей С++ in depth. 
Приходилось кому-либо в своих проектах определять собственный operator new, operator
new[] и т.п. или встречать в чужом коде? Если да, то с какой целью это было сделано?    


Ответы

Ответ 1



Я переопределяю new/delete в расширениях ПО, т.е. в динамических библиотеках, в которых используется STL и/или библиотеки, наследующие ее модель динамической памяти. Думаю, проблема "многокучности" известная, когда при инициализации CRT, в каждом модуле создается своя куча, которой пользуются глобальные методы управления памятью. Вот, чтобы расширения могли свободно интегрироваться во всех модулях ПО, и переопределяются операторы new/delete. Для этого, основной модуль экспортирует 2 метода, в которых вызывает malloc и free, соответственно, а каждое расширение переопределяет свой new/delete, вызывая в них эти 2 метода. Получается, что если расширения используют только глобальные new/delete, они все используют только одну кучу. А для корректной работы статических объектов, использующих кучу при инициализации, я перекрываю точку входа в DLL, импортируя эти 2 метода перед инициализацией CRT, после чего передаю управление встроенной _DllMainCRTStartup. Но есть нюанс, кторый нужно учесть при такой подстановке: первое, что нужно вызвать в точке входа - __security_init_cookie(): BOOL WINAPI MyDllStartup( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved ){ __security_init_cookie(); if( !::MyDllMainPreCRTStartup( hinstDLL, fdwReason, lpReserved ) ){ return FALSE; } return _DllMainCRTStartup( hinstDLL, fdwReason, lpReserved ); } p.s.: вместо malloc и free можно вызывать глобальные new/delete, это уже не принципиально.

Ответ 2



Было дело. Переопределял new для подсчета выделяемой памяти. Помнится тем же способом пытался ловить утечки памяти. И как-то пробовал писать свой менеджер памяти. В общем переопределять new скорее для развлечения. В реальных задачах это в общем-то не нужно.

Ответ 3



Я делал такое всего один раз. Нужно было сделать кэш для объектов, о котором бы ничего не знал код, эти объекты создающий. Код был не мой, и трогать его совершенно не хотелось. Но надо было как-то пресечь постоянное пересоздание одних и тех же объектов. В чужом коде видел такое только в книге Александреску. Он там описывал, как сделать крутой менеджер памяти для маленьких блоков. Это считается?

Ответ 4



В своих. Допустим, есть такая задача: приложение должно захватывать столько памяти, сколько сказано в конфиге, не больше. Точнее даже так: при старте захатывается кусок памяти, и всё выделение идёт только внутри него. Потом, в некоторых случаях вешается сторонний CG, в некоторых - нужна своя отладка выделения/освобождения...

Ответ 5



Я использовал, чтобы некоторые классы размещались в специальном хранилище, которое чистится при завершении потока. Там в деструкторах не было ничего, кроме уничтожения зависимых объектов, смысл был в том, чтобы убрать всё это крохоборство из деструкторов в менеджер памяти, который зачищает всю память оптом. Опыт скорее не понравился. Много писанины, польза туманна. На сегодняшний день имею мнение, что интегрировать внутрь класса логику размещения в памяти бессмысленно. Если хочешь принудить класс к работе через нестандартный менеджер памяти — закрой конструкторы и создавай экземпляры особой фабрикой. Если классу размещение не важно, нестандартный менеджер доступен через размещающий конструктор. А встраивание new/delete в класс — странная херня, смесь бульдога с крокодилом. Сказанное не относится к переопределению глобальных new/delete, с которыми свой геморрой, но есть и польза.

Ответ 6



Вообще в проектах не видел. Если не рассматривать только какие-то теоретические примеры из книг. Зачем это может понадобиться - могу представить. Например, в ситуации, когда так или иначе стандартный оператор работает неэффективно. Ну, или в целях отладки. Ведь, действительно, старую версию оператора ведь все равно можно вызвать :-) Из (полу-)коммерческих видел свой оператор new в MFC.

Ответ 7



Да, приходилось. Но больше в embedded: дефолные реализации звали malloc()/free() тогда как нужно было использовать аллокатор RTOS (ThreadX). В другом проекте с той же RTOS был ещё и свой аллокатор с хитрой аллокацией памяти дабы уменьшить фрагментацию и сократить оверхеды на блочные выделения. Плюс тут же был простенький анализатор мемликов и логирование аллокаций. Первый случай - проект сам поднимал, поэтому и сам писал. Второй случай - уже было сделано. В своих были только эксперименты, что бы некоторые типы объектов выделялись из специального пула. Из популярного, всякие valgrind подменяют вызовы new/malloc/delete/free в целях анализа утечек, повреждений.

Комментариев нет:

Отправить комментарий