Привет! Есть такая задача: В некой точке А программы выделяем память под структуры в точке Б удаляем(думаем, что удаляем) все структуры в точке С нужно проверить вся ли память выделенная под структуры в точек А была освобождена. Нужно знать в точности до байта. Есть ли простые способы для этого мониторинга? На С, конечно. Может случится следующий сценарий: Все указатели на структуры показывают на NULL. Но память у одной или нескольких не освобождена.
Нашел кажется кое-что интересное http://www.codeguru.com/forum/showthread.php?t=312742 Оцените, коллеги.
Я обычно проверяю, цикличиски прокручивая участки кода, если вижу что растет размер потребляемой памяти, пересматриваю все malloc\free. То что по ссылке, там предлагают использовать класс с деструктором который освободит память, это уже С++. PS Пишите лучше хороший и качественный код без memory leak, либо переходите на java.
в этой части: _CrtMemState s1, s2, s3; _CrtMemCheckpoint( &s1 ); // memory allocations take place here _CrtMemCheckpoint( &s2 ); if ( _CrtMemDifference( &s3, &s1, &s2) ) _CrtMemDumpStatistics( &s3 ); Нет никакого С++ На жабе тоже можно навыделять объектов, которые будут болтаться без дела, так как до garbage collector дело может не дойти. По GC есть даже целая книга(очень толстая) для программеров C#. Раз я сделал прогу на шарпе отожрала 500 метров, но работала благо комп был мощный.
Вместо malloc и free используй свои функции(которые могу сами вызывать malloc\free) и запоминай какая память была освобождена, а какие указатели в free не переданы
возможно, оптимальным способом будет использование http://www.hpl.hp.com/personal/Hans_Boehm/gc/ http://en.wikipedia.org/wiki/Boehm_garbage_collector в инклудах к нему есть хидера подменяющие стандартные маллокеры, включая new для С++ для линей может быть использован http://valgrind.org/ ну и случаи когда struct A { struct A* p; } a, b, c, d; a.p = &b; b.p = &c; c.p = &d; d.p = &a; вообще плохо поддаются детекции.
neutronion Чем не устраивает решение в лоб? Ну вот как-то примерно так Код (Text): typedef struct { void* ptr; size_t bytes; } allocation; unsigned maxAllocs = 1024; allocation* allocs; void _start() { if (allocs != NULL) return; if ((allocs = (allocation*) calloc (sizeof(allocation), maxAllocs)) == NULL) return; } void _stop() { unsigned i; if (allocs == NULL) return; for (i = 0; i < maxAllocs; ++i) { if (allocs[i].ptr != NULL) { printf("MEMORY LEAK: %d bytes allocated at %p was not freed within the control region\n", allocs[i].bytes, allocs[i].ptr); } } free (allocs); allocs = NULL; } void* _malloc (size_t byteCount) { void* p; if ((p = malloc (byteCount)) != NULL) { unsigned i; // add synchronization for safe multithread access for (i = 0; i < maxAllocs; ++i) { if (allocs[i].ptr == NULL) { allocs[i].ptr = p; allocs[i].bytes = byteCount; return p; } } // no free slots free (p); } return NULL; } void _free (void* p) { unsigned i; // add synchronization for safe multithread access for (i = 0; i < maxAllocs; ++i) { if (allocs[i].ptr == p) allocs[i].ptr = NULL; } free (p); } #define malloc(bc) _malloc(bc) #define calloc(x,y) _malloc(x*y) #define free(p) _free(p)
мне кажется, что лучше при аллокации добавлять к выделенной памяти хедер, объединяющий все аллоки в двусвязный список, а юзеру возвращать prt + sizeof(header)... так можно избежать проблем с максимальным числом аллоков, и обойтись одной статической переменной lastalloc...
Rel void* _malloc(int len){ void* p = malloc(len + sizeof(header)); ((header*)p)-> ... // устанавливаем хидер return p + sizeof(header); } char* a = _malloc(len_of_string); a[-3] = .. // пишем чтото --- речь ведь идет о поиске ошибки, правда? почему не допустить что она изза анормальной деятельности программы?
значит список хедеров держать отдельно от аллоцированной памяти... и кстати у подобного подхода (и моего и Грейта) есть один большой недостаток - возможная баго-генерация при использовании этих функций несколькими потоками, надо дополнять код мьютексом или любой другой темой)) хотя о какой стабильной многопоточности может идти речь, если программист допускает утечки по памяти...
Чем плох этот вариант в тестировании. Код (Text): _CrtMemState s1, s2, s3; _CrtMemCheckpoint( &s1 ); // здесь делаем выделения памяти и освобождение _CrtMemCheckpoint( &s2 ); if ( _CrtMemDifference( &s3, &s1, &s2) ) { //если попали сюда, значит утечка _CrtMemDumpStatistics( &s3 ); } По-моему проще. 4 строки кода. Речь в принципе идет о том, чтобы в процессе изготовления кода, тестировать его блочно на предмет утечек памяти, сначала мелкие функции , потом крупные части, которые используют уже оттестированные функции. Такая идея. Вопрос в том, может ли вышеописанная конструкция детектирования утечек подвести в каком-нибудь сценарии.
Rel вол так и делает. хотя нет, там все сложнее. там используется перетрансляция кода и контроль над каждым обращением к памяти + общий контроль при уходах в ядро. но боехм позволяет все это решить гораздо проще. без необходимости чтото переписывать или особо изучать.
Вот для простоты Код (Text): _CrtMemState s1, s2, s3; void StartLeakDetection() { //s1, s2, s3; надо бы здесь их обнулить _CrtMemCheckpoint( &s1 ); } bool StopLeakDetection() { _CrtMemCheckpoint( &s2 ); if ( _CrtMemDifference( &s3, &s1, &s2) ) { //leak!!!!! return false; } return true; } void Main() { StartLeakDetection(); //здесь делаем выделения и освобождения if(true != StopLeakDetection()) { //утечка!!!! } }
есть такой интересный подход, выделяем память,но в первые 4 байта выделенной памяти пишем магическое число. Соответственно выделяем памяти на 4 байта больше чем необходимо, чтобы особо не утруждаться можно писать это маг. число в конец. Кроме того можно будет проверить выделенную память, когда эта память еще не возвращена системе, если не находим магическое число, кто-то его уже покоцал. Перед освобождением памяти перезаписываем эту область памяти нулями. Затем освобождаем. После сканируем память на предмет магических чисел. Если что-то нашли, значит не вся память была возвращена системе. У кого-то умного прочитал, не помню у кого. Кажется Code complete(Совершенный код) книжка.
neutronion в процессе расчетов в памяти появились целые острова магических чисел. не относящихся к подобной защите. просто некоторые значения равные магическому числу.