С++, как обнаружить утечку памяти
ПРОГРАММ: 649 | СТАТЕЙ: 104 | КОДОВ: 3433   

    главная        новости        программы        библиотека        коды        рейтинг       форум   

Афоризм
Бритвенный станок с плавающей боеголовкой.
 
5 лучших
  Ставки на спорт
  Все о джазе, ноты, миди, биографии, фотографии
  В гостях у Грёблина
  Клуб Азарта
  Gansta-Rap Портал о 50Cent G-unit DMX D12 Dr.Dre
 
Поиск


 
Рассылка
| Soft-Ежедневник - обзор программ прямо к Вам на e-mail
 
 

  Библиотека > программирование > C++добавить статью
С++, как обнаружить утечку памяти

При разработке больших приложений, оперирующих большими объемами информации на первое место при отладке встает проблема обнаружения...
 
realcoding.net
winsov.ru
10-05-2004
Версия для печати
печать

Введение

При разработке больших приложений, оперирующих большими объемами информации на первое место при отладке встает проблема обнаружения неправильного распределения памяти. Суть проблемы состоит в том, что если мы выделили участок памяти, а затем освободили не весь выделенный объем, то образуются блоки памяти, которые помечены как занятые, но на самом деле они не используются. При длительной работе программы такие блоки могут накапливаться, приводя к значительному расходу памяти.

Для обнаружения подобных ошибок создано специализированное программное обеспечение (типа BoundsChecker от Numega), однако чаще бывает удобнее встроить механизм обнаружения утечки в свои проекты. Поэтому метод должен быть простым, и в то же время как можно более универсальным. Кроме того, не хотелось бы переписывать годами накопленные мегабайты кода, написанного и отлаженного задолго до того, как вам пришло в голову оградить себя от ошибок. Так что к списку требований добавляется стандартизация, т.е. нужно каким-то образом встроить защиту от ошибок в стандартный код.

Предлагаемое решение основывается на перегрузке стандартных операторов распределения памяти new и delete. Причем перегружать мы будем глобальные операторы new|delete, т.к. переписать эти операторы для каждого разработанного ранее класса было бы очень трудоемким процессом. Т.о. после перегрузки нам нужно будет только отследить распределение памяти и, соответственно, освобождение ее в момент завершения программы. Все несоответствия - ошибка.

Реализация

Проект написан на Visual C++, но переписать его на любой другой диалект С++ не будет слишком сложной задачей. Во-первых, нужно переопределить стандартные операторы new и delete так, чтобы это работало во всех проектах. Поэтому в stdafx.h добавляем следующий фрагмент:



#ifdef _DEBUG inline void * __cdecl operator new(unsigned int size, const char *file, int line) { }; inline void __cdecl operator delete(void *p) { }; #endif

Как видите, переопределение операторов происходит в блоке #ifdef/#endif. Это ограждает наш код от влияния на релиз компилируемой программы. Вы, наверное, заметили, что теперь оператор new имеет три параметра вместо одного. Два дополнительных параметра содержат имя файла и номер строки, в которой выделяется память. Это удобно для обнаружения конкретного места, где происходит ошибка. Однако код наших проектов по-прежнему ссылается на оператор new, принимающий один параметр. Для исправления этого несоответствия нужно добавиить следующий фрагмент



#ifdef _DEBUG #define DEBUG_NEW new(__FILE__, __LINE__) #else #define DEBUG_NEW new #endif #define new DEBUG_NEW

Теперь все наши операторы new будут вызываться с тремя параметрами, причем недостающие параметры подставит препроцессор. Конечно, пустые переопределенные функции ни в чем нам не помогут, так что давайте добавим в них какой-нибудь код:



#ifdef _DEBUG inline void * __cdecl operator new(unsigned int size, const char *file, int line) { void *ptr = (void *)malloc(size); AddTrack((DWORD)ptr, size, file, line); return(ptr); }; inline void __cdecl operator delete(void *p) { RemoveTrack((DWORD)p); free(p); }; #endif

Для полноты картины нужно переопределить операторы new[] и delete[], однако никаких существенных отличий здесь нет - творите!

Последний штрих - пишем функции AddTrack() и RemoveTrack(). Для создания списка используемых блоков памяти будем использовать стандартные средства STL:



typedef struct { DWORD address; DWORD size; char file[64]; DWORD line; } ALLOC_INFO; typedef list<ALLOC_INFO*> AllocList; AllocList *allocList; void AddTrack(DWORD addr, DWORD asize, const char *fname, DWORD lnum) { ALLOC_INFO *info; if(!allocList) { allocList = new(AllocList); } info = new(ALLOC_INFO); info->address = addr; strncpy(info->file, fname, 63); info->line = lnum; info->size = asize; allocList->insert(allocList->begin(), info); }; void RemoveTrack(DWORD addr) { AllocList::iterator i; if(!allocList) return; for(i = allocList->begin(); i != allocList->end(); i++) { if((*i)->address == addr) { allocList->remove((*i)); break; } } };

Перед самым завершением программы наш список allocList содержит ссылки на блоки памяти, котороые не были освобождены. Все, что нужно сделать - вывести эту информацию куда-нибудь. В нашем проекте мы выведем список неосвобожденных участков памяти в окно вывода отладочных сообщений Visual C++:



void DumpUnfreed() { AllocList::iterator i; DWORD totalSize = 0; char buf[1024]; if(!allocList) return; for(i = allocList->begin(); i != allocList->end(); i++) { sprintf(buf, "%-50s: LINE %d, ADDRESS %d %d unfreed ", (*i)->file, (*i)->line, (*i)->address, (*i)->size); OutputDebugString(buf); totalSize += (*i)->size; } sprintf(buf, "-------------------------------------------------- "); OutputDebugString(buf); sprintf(buf, "Total Unfreed: %d bytes ", totalSize); OutputDebugString(buf); };

Надеюсь, этот проект сделает ваши баг-листы короче, а программы устойчивее. Удачи!



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

Валера | 03-05-06 11:58
а как переделать сие чудо под C++Builder ???

Имя:
E-mail:
Сообщение:


Число:

   очистить

популярные статьи по теменовые статьи
Плохой и хороший траффик
web - разработка / Раскрутка в сети
Наука о web-браузерах
web - разработка / Сайтостроительство
Опытный заказчик + опытный дизайнер = хороший дизайн
web - разработка / Web-дизайн
О технике интернет-рекламы
web - разработка / Раскрутка в сети
Flash-технология. Недостатки
web - разработка / Web-дизайн
Загрузка ...

Опрос
На что Вы обращаете внимание в первую очередь при покупке товара в интернет-магазине?  
 
Комментарии и оценку пользователей
Наличие нескольких фотографий
Подробное и качественное описание
Условия доставки
Возможность покупки в кредит
 
Самое свежее  
 ПРОГРАММЫ

eMule 0.49a
eMule 0.49a

CPU-Z 1.45
CPU-Z 1.45

#1 DVD Ripper 7.2.4
#1 DVD Ripper 7.2.4

 НОВОСТИ

Мы победили! Олимпиада 2014 пройдет в Сочи
Мы победили! Олимпиада 2014 пройдет в Сочи

Алкогольный и наркотический террор против России
Алкогольный и наркотический террор против России

 БИБЛИОТЕКА

Плохой и хороший траффик
Плохой и хороший траффик

Наука о web-браузерах
Наука о web-браузерах

 
Рекомендую!





тИЦ

Copyright © 2004-2008 MostInfo.net  | связь с админом
При использовании материалов сайта ссылка на MostInfo обязательна.