Съвети програмисти и Trix улов изтичане на памет

В "Task Manager" е много често да се види, че някои програми заемат доста неприлично количество памет. Това е особено характерно за интернет браузъра. Рано или късно, изправена пред задачата да улов на изтичане на памет преди всеки разработчик. Днес ще се научите как да направите това в C ++, за MSVC.

Търсене на изтичане на памет, ще се работи на Windows, както и кода за монтаж използвате компилатор от Microsoft. Има много начини за избягване на лицата на паметта, но основното правило на тази борба може да бъде определена като "да се въведат всички, които взеха". За съжаление, "битка кодиране" не винаги е възможно. Колкото и банално човешки фактор или задействаната изключение може лесно да се откажете от оператора изтриете. В тази статия няма да се обсъдят какво да правят и какво не си струва да се памет не е изтекла. Ние ще действа в рамките на съществуващите проблеми: има изтичане и ние трябваше да го блокира.
За решаване на пъзели, много програмисти използват библиотеки на трети страни (и най-готините пишат свои управление на паметта), но ние ще започнем с нещо по-просто - например, чрез използване Debug CRT.

За да използвате Debug CRT е необходимо да се свържете подходящ хедър, и ще позволи използването на Debug Heap Alloc карта. Това се прави само с няколко реда код:

Свързване на Debug CRT

#ifdef _DEBUG
#include
#define _CRTDBG_MAP_ALLOC
# endif

След тези стъпки, разпределението на паметта, като нови и изчистване () данни ще бъдат увити в специална структура _CrtMemBlockHeader. С тази обвивка можем да намерим името на файла и линията, която е запазена liknutaya памет, неговия обем и самите данни. Всички записи са обединени в списък с двойно-свързани, така че върху него е лесно да се работи и да намерите проблемни области.

структура _CrtMemBlockHeader

typedef структура _CrtMemBlockHeader
Struct _CrtMemBlockHeader * pBlockHeaderNext;
Struct _CrtMemBlockHeader * pBlockHeaderPrev;
знак * szFileName;
Int nLine;
size_t nDataSize;
Int nBlackUse;
дълго lRequest;
неподписан празнина овъгляване [nNoMansLandSize];
неподписани данни харак [nDataSize];
неподписан овъгляване anotherGap [nNoMansLandSize];

За да мине през този списък, ще трябва да използвате функцията _CrtDumpMemoryLeaks (). Отнема няма параметри и просто показва списък с изтеклите блокове памет. Но, за съжаление, той не ни казва нищо за файла и линията, в която е разпределена памет. В резултат на тази функция изглежда така:

Заключение _CrtDumpMemoryLeaks ()

Откритите течове памет!
Дъмпинг обекти ->
Нормално блок в дългосрочен 0x00128788, 4 байта.
данни: <> 00 00 00 00
Нормално блок в дългосрочен 0x00128748, 4 байта.
данни: <> 00 00 00 00
сметище Object пълна.

Ето как: в Microsoft Visual C ++ 6.0 е предефиниране на нови функции в crtdbg.h файл, на която беше да се покаже точно файла и линията, в която разпределението се състоя. Но това не даде желания резултат - файла: Ред винаги разгърна в crtdbg.h файл линия 512. В следващите версии на Microsoft премахната тази функция изобщо, както и цялата тежест на отговорността лежеше на програмистите. Направи нормален изход, можете да използвате следните замените на

Императивно нов

#define нов нов (_NORMAL_BLOCK, __FILE__, __LINE__)

Тази линия, е желателно да се извърши по някакъв общ файл заглавието и го свържете след crtdbg.h. Сега нашата задача е да го напиша във всеки регистър, или най-малкото в изходната конзола. За да пренасочите изхода имаме нужда от две функции: _CrtSetReportMode и _CrtSetReportFile. Вторият параметър може да бъде дръжка _CrtSetReportFile нашия лог файл или изход флаг за стандартния изход.

Пренасочване на изхода

_CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE);
// показва всички стандартния изход
_CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDOUT);

При този метод има един проблем - това показва информация на паметта не е изтекла, но просто не са имали време да се върне. Това, например, може да бъде всеки глобална променлива или обект. Ние трябва по някакъв начин да се премахнат тези блокове памет от изходните _CrtDumpMemoryLeaks (). Това се прави по следния начин:

Ограничаване покритие _CrtDumpMemoryLeaks ()

Int _tmain (междинно argc, _TCHAR * argv [])
_CrtMemState _ms;
_CrtMemCheckpoint (_ms);
// някои логика отива тук.
_CrtMemDumpAllObjectsSince (_ms);
връщане 0;
>

Записваме първоначалното състояние на паметта в специална структура с помощта на функцията _CrtMemCheckpoint (), и в крайна сметка, като се използва _CrtMemDumpAllObjectsSince (), получаваме всичко, което течеше след направихме отливка на ума.

Това е начина, с помощта на прости функции Debug CRT, ние можем да се борим ефективно с лицата на паметта в нашата програма. Разбира се, това не е заместител на сериозни библиотеки за улавяне на течове, но това е доста подходящ за по-малки проекти.

Visual Leak Detector

Visual Leak Detector - това е трета страна, библиотека, но в действителност това е добавка за отстраняване на грешки CRT, които смята за малко по-рано. Използвайте го е съвсем проста - просто трябва да се включат vld.h заглавния файл в друг файл на проекта. Но с две уговорки.

На първо място, ако го направим проекта има множество двоични модули (DLL или EXE), а след това да включва за vld.h трябва да се направи поне един източник на файла за всеки модул. Това означава, че ако имаме след съставянето на данните е module_1.dll и module_2.dll, тогава ние трябва да направим #include най-малко module_1.h и module_2.h.

На второ място, включването на заглавната част на файла Visual Leak Detector трябва да се случва, след като prekompiled Хедър. Това означава, че след stdafx.h, както и други подобни файлове. След изпълнението на тези условия е достатъчно, за да стартирате програмата в отстраняване на грешки изгражда и библиотеката веднага ще започне да работи.

Visual Leak Detector могат да бъдат персонализирани с вашите нужди. Config съхранява в vld.ini файл, който, от своя страна, е в директорията с VLD. В този конфигурационен файл може да се копира в папката на проекта, а след това на библиотеката ще използва този екземпляр с индивидуални настройки за всеки проект.
Настройки за Visual Leak Detector тунинг изобилстват. Например, можете да конфигурирате и същ резултат на файл или в конзолата за студио за отстраняване на грешки. Тя се превръща в ключов ReportTo. Настройката по подразбиране е "дебъгер», но можете да промените стойността на «файл» или «двете». Надявам се да се обясни значението им не е необходимо.

Ако се включи изхода към файл, трябва да укажете пътя до този файл с помощта на параметър ReportFile. Можете също да изберете кодирането на файла чрез ReportEncoding: уникод или ASCII.

И все пак има една интересна опция за търсене на лицата в самата библиотека (Автотест). Да, това се случва понякога. Ако се опитате, можете да получите на изхода нещо като това:

ГРЕШКА: Visual Leak Detector: Установена изтичане на памет, вътрешни за Visual Leak Detector.

Друг VLD ви позволява да ограничите размера на изхода на сметището в лог или дори потискат това заключение, както и регулиране на дълбочината на проникване на метод на комина, и така нататък. Но това е специфично нещо, което може да е полезно за някои, а не някои. Като цяло Visual Leak Detector е прост, лесен за употреба и не изисква много код за активиране на изтичане на режим на търсене.

Всичко, което ние разгледахме по-горе, това е важно както за Windows и MS Visual Studio. Но има и други операционни системи. Valgrind само за тях. Тя работи на Linux и Mac OS X и се използва не само за улавяне на лицата на паметта, но и за отстраняване на грешки на паметта и профилиране (колекция предлага работната програма). В действителност, Valgrind е виртуална машина, използвайте метод СЕР-компилиран. усилие й не се изпълнява директно на процесора на компютъра, и е преведен на така наречената "междинна представителство". С оглед на това и работи Valgrind. По-точно, неговите инструменти работят, но малко по-късно за това.

След обработване на междинно съединение представяне Valgrind превъзхожда всички обратно в машинен код. Тези действия значително (4-5 пъти) забавят изпълнението на програмата. Но това е съвсем разумна такса за контрол на изразходването на паметта. Както казах по-горе, Valgrind предоставя няколко инструмента. Най-популярните от тях - Memcheck. Тя замества стандартния избор на изпълнението на C език на собствената си памет. Memcheck открива опити неподготвен за използването на паметта, четене / писане след освобождаването му от края и избрания блок, както и изтичане на памет.

Има и други инструменти, като например Addrcheck - по-лесно, но по-малко функционална версия Memcheck. Helgrind инструменти и ДРД се използват за намиране на грешки в многонишков код. С други думи, Valgrind много по-мощни нещо от просто една библиотека, за да открие лица на паметта.

заключение

изтичане на памет - един от най-честите проблеми в програмирането. Дори и най-опитните от нас могат да се сдобият с няколко лица. Инструменти за улавяне на тяхното голямо разнообразие, както и тези няколко страници, за да ви помогнат да се бори с изтичане на памет.

Покажете тази статия на приятел: