12.07.2015 Views

img - Xakep Online

img - Xakep Online

img - Xakep Online

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CODINGCODINGЛЕЙТЕНАНТ РОМАН «PREDIDENTUA» ХОМЕНКО /HTTP://TUTAMC.COM/Программирование — нелегкая штука, а на C++ —тем болеезываются очень полезными знания о том, как используется память: какраспределены выделяемые блоки по размерам, каково время их жизни,какой порядок выделения и освобождения блоков характерен для кода,изменяется ли «потребление» динамической памяти на разных стадияхвыполнения программы, и есть ли вообще какая-либо закономерность.На все эти вопросы помогут ответить собственные операторы работы спамятью.Ïðèìåð ñîáñòâåííîé âåðñèè newНаписать собственную версию операторов new и delete достаточно просто.Рассмотрим, например, как можно реализовать глобальный операторnew с контролем записи за границами выделенного блока. Правда, впримере ниже есть несколько недостатков, но об этом далее.Пользовательская версия оператора newstatic const int signature = 0xADADEAEA;typedef unsigned char Byte;void *operator new(std::size_t size)throw(std::bad_alloc){using namespace std;size_t realSize = size + 2 * sizeof(int);void *pMem = malloc(realSize);if (!pMem)throw(bad_alloc);*(static_castpMem)) = signature;*(reinterpret_cast(static_cast(pMem)+ realSize — sizeof(int))) = signature;}116return static_cast(pMem) + sizeof(int);Здесь мы сначала с помощью функции malloc выделяем блок памяти надва слова больше, чем запрашивается в передаваемом параметре, затемзаписываем сигнатуру в начало и в конец выделенного куска памяти, послечего возвращаем указатель на нее.Вроде все хорошо, но мы забываем о такой важной вещи, как выравнивание.Многие компьютерные архитектуры требуют, чтобы данные определенныхтипов располагались в памяти по вполне конкретным адресам.Например, архитектура может требовать, чтобы указатели располагалисьпо адресам, кратным четырем, а данные типа double были выровнены награницу двойного четырехбайтного слова. Если не соблюдать эти требования,то возможны аппаратные сбои или замедление работы системы.C++ требует, чтобы все указатели, возвращаемые оператором new, былиОтличная книга по стандарту С++выровнены для любого типа данных. Функция malloc удовлетворяетэтим условиям, но, поскольку мы записываем в начало блока сигнатуру,и, следовательно, возвращаем указатель, смещенный на длину этойсигнатуры, то нет никаких гарантий, что это безопасно. Если мы выделимпамять под переменную типа double на компьютере с архитектурой, где intзанимает четыре байта, то оператор new, приведенный в примере, скореевсего вернет неправильный указатель, что в итоге может завершитьсяаварийной остановкой программы или ее сильным замедлением.Надеюсь, теперь понятно, почему правильное выравнивание так важно.Но не менее важным является требование к операторам new, согласно которомувсе они должны включать цикл вызова функции-обработчика new.Ôóíêöèÿ-îáðàáîò÷èê newКогда оператор new не может удовлетворить запрос на выделение запрошенногоколичества памяти, он возбуждает исключение. В старыевремена оператор new возвращал ноль и следы подобного поведениясохранились в некоторых компиляторах и по сей день. Основная же массасовременных компиляторов генерирует код с new, поддерживающимвызов исключений.Перед тем как вызвать исключение после неудачной попытки выделенияпамяти, оператор new должен выполнить код функции-обработчика (newhandler),которая определяется пользователем. Чтобы задать обработчик,нужно вызвать стандартную библиотечную функцию set_new_handler,объявленную в заголовочном файле следующим образом:Объявление set_new_handlernamespace std {typedef void (*new_handler) ();XÀÊÅÐ 08 /139/ 10

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!