Ошибка: Failed to parse the Currency Converter XML document.
$11 694.96


Ошибка: Failed to parse the Currency Converter XML document.
$1 495.89


Ошибка: Failed to parse the Currency Converter XML document.
$1 975.50


Как обнаружить утечку памяти

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

Как обнаружить утечку памяти
Введение

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


Для обнаружения подобных ошибок создано специализированное программное обеспечение (типа 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;
    DWORDsize;
    charfile[64];
    DWORDline;
} ALLOC_INFO;

typedef list 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:\tLINE %d,\tADDRESS %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);
};

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

 

Интересное

Основы файловой системы...
Сегодня мы заглянем в дебри файловой системы WindowsXP. Что такое файловая система — это организация хранения Ваших файлов на жестком (или любом другом диске). На разных видах дисков в разных...
Подробнее...
Продлеваем жизнь Windows XP
<img src=«http://i-faq.ru/uploads/posts/2007-09/1190884587_computer.jpg» align=«left» style=«border: none;» alt=«Продлеваем жизнь Windows XP» />Windows Vista можно назвать яркой и новой, но...
Подробнее...
Обзор и установка системы...
ВведениеДумаю, в настоящее время никто уже не станет спорить с утверждением, что процесс вхождения Linux в корпоративный мир стал необратимым, а процент установок этой операционной системы на...
Подробнее...
Проблема медленного...
Кто бы чего не говорил, но операционная система Windows XP, зарекомендовала себя как достаточно надежная (при надлежащем отношении). Моя копия Windows XP SP1, в последующем обновленная до SP2,...
Подробнее...
Внимание! Отказ в...
Описание: Уязвимость позволяет удаленному пользователю вызвать отказ в обслуживании приложения.Уязвимость существует из-за ошибки при обработке пакетов, отправленных на порт 48000 UDP/TCP....
Подробнее...
Стиль против Дизайна
От Дизайна к СтилюМой отец был полупрофессиональным художником (Sunday painter), книжки с его иллюстрациями сыграли для меня в детстве формирующую роль. Как и многие другие дети, я зачаровывался...
Подробнее...
Уроки программирования на...
В данной книге будут рассматриваться самые эффективные способы написания кода с помощью классов MFC(Microsoft Foundation Class Library). Вы пройдете весь курс за пару дней. Примеры несложные,...
Подробнее...
Обзор вариантов прокладки...
Если кто-то пытается убедить вас, что создание сети — дело сложное, не верьте: на самом деле, оно очень сложное. Тем не менее, если не замахиваться сразу на масштаб промышленного предприятия,...
Подробнее...
Установка Windows Server...
Семейство продуктов Windows Server 2003 берет все самое лучшее от технологии ОС Windows 2000 Server, упрощая при этом развертывание, управление и использование.В результате пользователь получает...
Подробнее...
Взаимодействие с чужими окнами
Представьте себе, глупый пользователь сидит как ни в чём небывало с умным видом уже в какой раз пытается составить документ в Microsoft Word'e, но вдруг окно начинает бешено скакать по экрану, в...
Подробнее...