Задача ослеживания утечек памяти.

Тема в разделе "LANGS.C", создана пользователем neutronion, 3 мар 2011.

  1. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Привет! Есть такая задача:
    В некой точке А программы выделяем память под структуры
    в точке Б удаляем(думаем, что удаляем) все структуры
    в точке С нужно проверить вся ли память выделенная под структуры
    в точек А была освобождена. Нужно знать в точности до байта.
    Есть ли простые способы для этого мониторинга? На С, конечно.
    Может случится следующий сценарий:
    Все указатели на структуры показывают на NULL. Но память у одной или нескольких не освобождена.
     
  2. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
  3. Sunzer

    Sunzer Member

    Публикаций:
    0
    Регистрация:
    25 май 2008
    Сообщения:
    256
    Я обычно проверяю, цикличиски прокручивая участки кода, если вижу что растет размер потребляемой памяти, пересматриваю все malloc\free.

    То что по ссылке, там предлагают использовать класс с деструктором который освободит память, это уже С++.

    PS Пишите лучше хороший и качественный код без memory leak, либо переходите на java.
     
  4. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Как определяете, что растет потребляемая память?
     
  5. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    в этой части:
    _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 метров, но работала благо комп был мощный.
     
  6. Sunzer

    Sunzer Member

    Публикаций:
    0
    Регистрация:
    25 май 2008
    Сообщения:
    256
    В диспетчере задач
     
  7. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    в килобайтах? Не очень аккуратно. ...И опрометчиво.
     
  8. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    Вместо malloc и free используй свои функции(которые могу сами вызывать malloc\free) и запоминай какая память была освобождена, а какие указатели в free не переданы
     
  9. fsd

    fsd New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2010
    Сообщения:
    353
    DevParnter/AQTime/Intel Parallel Studio/Deleaker и тп
     
  10. Rustem

    Rustem New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2004
    Сообщения:
    429
    Адрес:
    Russia
    Попробуй Visual Leak Detector

    http://habrahabr.ru/blogs/cpp/113567/
     
  11. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    возможно, оптимальным способом будет использование

    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;

    вообще плохо поддаются детекции.
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    neutronion
    Чем не устраивает решение в лоб?

    Ну вот как-то примерно так
    Код (Text):
    1. typedef struct
    2. {
    3.     void* ptr;
    4.     size_t bytes;
    5. } allocation;
    6.  
    7. unsigned maxAllocs = 1024;
    8. allocation* allocs;
    9.  
    10. void _start()
    11. {
    12.     if (allocs != NULL)
    13.         return;
    14.    
    15.     if ((allocs = (allocation*) calloc (sizeof(allocation), maxAllocs)) == NULL)
    16.         return;
    17. }
    18.  
    19. void _stop()
    20. {
    21.     unsigned i;
    22.    
    23.     if (allocs == NULL)
    24.         return;
    25.    
    26.     for (i = 0; i < maxAllocs; ++i)
    27.     {
    28.         if (allocs[i].ptr != NULL)
    29.         {
    30.             printf("MEMORY LEAK: %d bytes allocated at %p was not freed within the control region\n",
    31.                 allocs[i].bytes, allocs[i].ptr);
    32.         }
    33.     }
    34.    
    35.     free (allocs);
    36.     allocs = NULL;
    37. }
    38.  
    39. void* _malloc (size_t byteCount)
    40. {
    41.     void* p;
    42.    
    43.     if ((p = malloc (byteCount)) != NULL)
    44.     {
    45.         unsigned i;
    46.        
    47.         // add synchronization for safe multithread access
    48.        
    49.         for (i = 0; i < maxAllocs; ++i)
    50.         {
    51.             if (allocs[i].ptr == NULL)
    52.             {
    53.                 allocs[i].ptr = p;
    54.                 allocs[i].bytes = byteCount;
    55.                
    56.                 return p;
    57.             }
    58.         }
    59.        
    60.         // no free slots
    61.         free (p);
    62.     }
    63.    
    64.     return NULL;
    65. }
    66.  
    67. void _free (void* p)
    68. {
    69.     unsigned i;
    70.    
    71.     // add synchronization for safe multithread access
    72.  
    73.     for (i = 0; i < maxAllocs; ++i)
    74.     {
    75.         if (allocs[i].ptr == p)
    76.             allocs[i].ptr = NULL;
    77.     }
    78.  
    79.     free (p);
    80. }
    81.  
    82. #define malloc(bc)    _malloc(bc)
    83. #define calloc(x,y)   _malloc(x*y)
    84. #define free(p)       _free(p)
     
  13. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    мне кажется, что лучше при аллокации добавлять к выделенной памяти хедер, объединяющий все аллоки в двусвязный список, а юзеру возвращать prt + sizeof(header)... так можно избежать проблем с максимальным числом аллоков, и обойтись одной статической переменной lastalloc...
     
  14. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    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] = .. // пишем чтото

    ---
    речь ведь идет о поиске ошибки, правда? почему не допустить что она изза анормальной деятельности программы?
     
  15. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    значит список хедеров держать отдельно от аллоцированной памяти... и кстати у подобного подхода (и моего и Грейта) есть один большой недостаток - возможная баго-генерация при использовании этих функций несколькими потоками, надо дополнять код мьютексом или любой другой темой)) хотя о какой стабильной многопоточности может идти речь, если программист допускает утечки по памяти...
     
  16. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Чем плох этот вариант в тестировании.
    Код (Text):
    1. _CrtMemState s1, s2, s3;
    2.  
    3. _CrtMemCheckpoint( &s1 );
    4. // здесь делаем выделения памяти и освобождение
    5. _CrtMemCheckpoint( &s2 );
    6.  
    7. if ( _CrtMemDifference( &s3, &s1, &s2) )
    8. {
    9.     //если попали сюда, значит утечка
    10.    _CrtMemDumpStatistics( &s3 );
    11. }
    По-моему проще. 4 строки кода.
    Речь в принципе идет о том, чтобы в процессе изготовления кода, тестировать его блочно на предмет утечек памяти, сначала мелкие функции , потом крупные части, которые используют уже оттестированные функции.
    Такая идея. Вопрос в том, может ли вышеописанная конструкция детектирования утечек подвести в каком-нибудь сценарии.
     
  17. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Rel
    вол так и делает. хотя нет, там все сложнее. там используется перетрансляция кода и контроль над каждым обращением к памяти + общий контроль при уходах в ядро.

    но боехм позволяет все это решить гораздо проще. без необходимости чтото переписывать или особо изучать.
     
  18. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Вот для простоты
    Код (Text):
    1. _CrtMemState s1, s2, s3;
    2.  
    3. void StartLeakDetection()
    4. {
    5.          //s1, s2, s3; надо бы здесь их обнулить
    6.     _CrtMemCheckpoint( &s1 );
    7. }
    8.  
    9. bool StopLeakDetection()
    10. {
    11.     _CrtMemCheckpoint( &s2 );
    12.     if ( _CrtMemDifference( &s3, &s1, &s2) )
    13.     {
    14.         //leak!!!!!
    15.         return false;
    16.     }
    17.     return true;
    18. }
    19.  
    20.  
    21. void Main()
    22. {
    23.     StartLeakDetection();
    24.  
    25.     //здесь делаем выделения и освобождения
    26.    
    27.     if(true != StopLeakDetection())
    28.     {
    29.         //утечка!!!!
    30.     }
    31.  
    32.  
    33. }
     
  19. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    есть такой интересный подход, выделяем память,но в первые 4 байта выделенной памяти пишем магическое число. Соответственно выделяем памяти на 4 байта больше чем необходимо, чтобы особо не утруждаться можно писать это маг. число в конец. Кроме того можно будет проверить выделенную память, когда эта память еще не возвращена системе, если не
    находим магическое число, кто-то его уже покоцал. Перед освобождением памяти перезаписываем эту область памяти нулями. Затем освобождаем.
    После сканируем память на предмет магических чисел. Если что-то нашли, значит не вся память была возвращена системе. У кого-то умного прочитал, не помню у кого.
    Кажется Code complete(Совершенный код) книжка.
     
  20. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    neutronion
    в процессе расчетов в памяти появились целые острова магических чисел. не относящихся к подобной защите. просто некоторые значения равные магическому числу.