18.11.2014 Views

JIT SPRAY АНАЛИЗ TDSS - Xakep Online

JIT SPRAY АНАЛИЗ TDSS - Xakep Online

JIT SPRAY АНАЛИЗ TDSS - Xakep Online

SHOW MORE
SHOW LESS

Create successful ePaper yourself

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

CODING<br />

deeonis deeonis@gmail.com<br />

КОДЕРСКИЕ<br />

ТИПСЫ И ТРИКСЫ<br />

Ïðàâèëà êîäèíãà íà C++ äëÿ íàñòîÿùèõ ñïåöîâ<br />

Ïðîäîëæàåì èçó÷àòü òîíêîñòè óïðàâëåíèÿ ïàìÿòüþ â C++.<br />

Ñëåäóþùèå ïàðà ñòðàíèö áóäóò ïîñâÿùåíû óãëóáëåííîìó<br />

èçó÷åíèþ îïåðàòîðîâ new è delete. Èç íèõ òû óçíàåøü, êàêèå<br />

òðåáîâàíèÿ ïðåäúÿâëÿåò ñòàíäàðò C++ ê ïîëüçîâàòåëüñêèì<br />

ðåàëèçàöèÿì ýòèõ îïåðàòîðîâ.<br />

В прошлой статье мы успели разобраться, для чего вообще нужно<br />

заменять операторы new и delete своими версиями, и в каких случаях<br />

без этого можно обойтись. Также мы немного затронули тему функцииобработчика<br />

new и обсудили проблему выравнивания возвращаемых<br />

указателей.<br />

Если ты не читал прошлые трюки, крайне советую прочитать августовский<br />

номер, поскольку в этой статье мы будем считать, что прошлые<br />

трюки ты все-таки осилил.<br />

Итак, к реализации пользовательских версий операторов new и delete<br />

C++ предъявляет определенные требования. Одно из этих требований<br />

мы рассмотрели в прошлом номере — это функция-обработчик new.<br />

О ней мы еще поговорим чуть ниже. Кроме того, самописный new<br />

должен возвращать правильное значение и корректно обрабатывать<br />

запросы на выделение нуля байтов. Также при реализации собственных<br />

функций управления памятью мы должны позаботиться о том,<br />

чтобы не скрыть их «нормальные» формы. Ну, а теперь обо всем этом<br />

подробнее.<br />

Ñîãëàøåíèÿ ïðè<br />

íàïèñàíèè îïåðàòîðà new<br />

Первым делом пользовательский new должен возвращать правильное<br />

значение. В случае успешного выделения памяти оператор должен<br />

вернуть указатель на нее. Если же что-то пошло не так, следует<br />

возбудить исключение типа bad_alloc.<br />

Но не все так просто, как кажется. Перед исключением new должен в<br />

цикле вызывать функцию-обработчик, которая попытается разрешить<br />

проблемную ситуацию. Что должна делать эта функция, мы подробно<br />

рассмотрели в прошлой статье. Сейчас я лишь напомню, что она может<br />

высвободить заранее заготовленный резерв памяти в случае ее<br />

нехватки, сама возбудить исключение или вовсе завершить программу.<br />

Крайне важно, чтобы функция-обработчик корректно отработала,<br />

поскольку цикл ее вызова будет выполняться до тех пор, пока не будет<br />

разрешена конфликтная ситуация. Следующий важный момент, который<br />

мы должны учитывать — это обработка запросов на выделение<br />

нуля байт памяти. Как ни странно это звучит, но стандарт C++ требует в<br />

этом случае корректной работы оператора. Такое поведение упрощает<br />

реализацию некоторых вещей в других местах языка. Принимая во<br />

внимание все это, можно попробовать накидать псевдокод пользовательского<br />

new:<br />

Псевдокод пользовательской реализации оператора new<br />

void *operator new(std::size_t size)<br />

{<br />

}<br />

throw(std::bad_alloc)<br />

using namespace std;<br />

// îáðàáîòàòü çàïðîñ íà 0 áàéòîâ,<br />

// ñ÷èòàÿ, ÷òî íóæíî âûäåëèòü 1 áàéò<br />

if (size == 0)<br />

size = 1;<br />

while(true)<br />

{<br />

// ïîïûòêà âûäåëèòü size áàéòîâ;<br />

}<br />

if (âûäåëèòü óäàëîñü)<br />

return (óêàçàòåëü íà ïàìÿòü);<br />

// âûäåëèòü ïàìÿòü íå óäàëîñü<br />

// ïðîâåðèòü, óñòàíîâëåíà ëè ôóíêöèÿ-îáðàáîò÷èê<br />

new_handler globalHandler = set_new_handler(0);<br />

set_new_handler(globalHandler);<br />

if (globalHandler)<br />

(*globalHandler) ();<br />

else<br />

throw std::bad_alloc();<br />

112 XÀÊÅÐ 09 /140/ 10

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

Saved successfully!

Ooh no, something went wrong!