JIT SPRAY ÃÂÃÂÃÂÛØ× TDSS - Xakep Online
JIT SPRAY ÃÂÃÂÃÂÛØ× TDSS - Xakep Online
JIT SPRAY ÃÂÃÂÃÂÛØ× TDSS - Xakep Online
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