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.

CODINGdeeonis deeonis@gmail.comКОДЕРСКИЕТИПСЫ И ТРИКСЫÏðàâèëà êîäèíãà íà C++ äëÿ íàñòîÿùèõ ñïåöîâÑ++ ÈÑÊÎÍÍÎ Ñ×ÈÒÀÅÒÑß ÃÈÁÊÈÌ, ÍÎ ÑËÎÆÍÛÌ, ßÇÛÊÎÌÏÐÎÃÐÀÌÌÈÐÎÂÀÍÈß. ÏÎ×ÅÌÓ? ÏÎÒÎÌÓ ×ÒÎ ÒÀÊ ÎÍÎ È ÅÑÒÜ :). ÝÒÎÉ ÑÒÀÒÜÅ ÌÛ ÓÇÍÀÅÌ ÎÁ ÎÏÅÐÀÒÎÐÀÕ NEW È DELETE, Î ÒÎÌ,ÊÀÊ ÏÈÑÀÒÜ ÑÎÁÑÒÂÅÍÍÛÅ ÏÐÎÖÅÄÓÐÛ ÓÏÐÀÂËÅÍÈß ÏÀÌßÒÜÞÈ ÊÀÊ ÍÅ ÑÎÂÅÐØÈÒÜ ÓÆÀÑÍÓÞ ÎØÈÁÊÓ, ÇÀÍÈÌÀßÑÜ ÝÒÈÌÍÅËÅÃÊÈÌ ÄÅËÎÌ.Многие кодеры, выбирая C++ в качестве основного языка для написаниясвоих программ, хотят тем самым добиться от них максимальнойэффективности, как в плане потребления ресурсов, так и в плане скоростивыполнения. Именно написание собственных операторов для работы спамятью дает такую возможность. Конечно, в наше время, когда повсеместноиспользуются сборщики мусора (например, в Java или C#), сам посебе вызов специальных команд для выделения и освобождения памятивыглядит немного странно, но именно благодаря этим командам любойпрограммист может значительно улучшить производительность своегокода.Для того, чтобы написать правильный код, который будет работать с памятью,надо понимать, как организованы процедуры управления этой самойпамятью в C++. Также следует помнить о многопоточности и проблемах,связанных с ней. Куча — это модифицируемый глобальный ресурс, доступк которому должен быть синхронизирован. Если игнорировать этот факт,то рано или поздно все сломается, и потом будет очень сложно разобраться,в чем же собственно дело. Поэтому при написании собственногоменеджера памяти всегда надо помнить о возможности одновременногодоступа к куче из разных потоков программы.Êîãäà èìååò ñìûñë çàìåíÿòünew è delete?Для начала давай разберемся, стоит ли нам вообще писать собственныепроцедуры работы с памятью. Чаще всего new и delete переписывают длятого, чтобы обнаружить так называемые ошибки применения. К такимошибкам относятся, например, утечки памяти. Они могут случаться как иззапростой невнимательности программиста, так и вследствие высокогоуровня сложности структуры кода. Попросту говоря, для динамическивыделенной памяти не всегда вызывается delete. Бывает и другая крайность,когда для одного и того же блока из кучи delete вызывается два иболее раз. В этом случае поведение программы предсказать невозможно.Всего этого можно избежать, если пользовательские функции по работеXÀÊÅÐ 08 /139/ 10с кучей будут вести список выделенных блоков памяти. Еще одной частовстречающейся ошибкой применения является переполнение буфера.Сколько хакерских атак было успешно выполнено через такую вот старую,как мир, дыру? Антагонист переполнения — это запись с адреса, предшествующегоначалу выделенного блока. Самописная версия new может запрашиватьблоки большего размера и записывать в начало и конец такихблоков специальную сигнатуру. Оператор delete может проверять наличиеэтой сигнатуры и, если ее не окажется на месте, поднимать тревогу.Второй причиной, из-за которой можно смело переписывать процедурыуправления памятью, является производительность. Стандартныеверсии операторов new и delete, поставляемые вместе с компилятором,«слишком» универсальны. Они должны одинаково хорошо работатькак для кода, выполнение которого занимает меньше секунды, так и дляпрограмм, аптайм которых составляет месяцы. Эффективно выделять какнесколько больших блоков памяти, которые существуют на протяжениивсей работы программы, так и множество маленьких, которые «живут»сотые доли секунды. Стандартные функции работы с кучей должны уметьэффективно бороться с ее фрагментацией, поскольку даже если суммарныйобъем свободной памяти будет достаточно велик, высокая степень ее«раздробленности» может помешать выделению нужного блока.Теперь понятно, почему дефолтные new и delete не всегда оказываютсябыстрыми и эффективными — используются слишком общие алгоритмыработы с памятью, которые призваны учесть все нюансы. В некоторыхслучаях написание собственных операторов работы с памятью помогаетзначительно ускорить выполнение кода, а также уменьшить расход ресурсов.Так, например, самописные new и delete будут полезны для ускоренияпроцесса распределения и освобождения памяти, для уменьшениянакладных расходов, характерных для стандартного менеджера памяти;чтобы компенсировать субоптимальное выравнивание в распределителяхпо умолчанию (об этом чуть ниже), чтобы сгруппировать взаимосвязанныеобъекты друг с другом и т.д.Еще очень часто new и delete переписывают для сбора статистики обиспользуемой памяти. В высоконагруженных приложениях часто ока-115

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

Saved successfully!

Ooh no, something went wrong!