The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
malloc/free in threads утечка памяти, !*! SaneK, 25-Апр-03, 12:22  [смотреть все]

Есть приложение, написанное на Си, использующее нити, работает по следующей схеме:

  При запуске приложения запускается основной поток далее по возникновению какого то события из этого потока запускаются другие потоки использующие одну глобальную переменную, память под которую выделяется malloc'ом в основном потоке и освобождается free в потоках которые запускаются из основного. Доступ к этой переменной разделяется с помощью мьютексов. Вроде прога работает, все нормально, но вот только память используемая ей все время растет (top'ом смотрю).

Подскажите в чем может быть причина?

Спасибо.

  • malloc/free in threads утечка памяти, !*! SaneK, 13:10 , 25-Апр-03 (1)
    Да, забыл, все это дело крутится на FreeBSD 4.6.2

  • malloc/free in threads утечка памяти, !*! David, 22:17 , 07-Май-03 (2)
    Покажите код, хотя бы те участки (только не одну строку), где выделяется и освобождается память. Иначе вам вряд ли кто-нить сможет помочь :)

    А так на вскидку скорее всего происходит так, что главный поток заново выделяет память до того, как её освободил один из дочерних, указатель теряется - память тоже.

    • malloc/free in threads утечка памяти, !*! SaneK, 17:06 , 13-Май-03 (4)
      Код примерно такой.
        
      *****************************************
      //Основной поток

          typedef struct
                      {
                       int Поле;
                      }pkt;

      .........
        //packet  - Глобальная переменная

        packet = (pkt *)calloc(Размер массива,sizeof(pkt));
        i = 0;
        while(1) {

      ....

      Заполняем packet (packet[i].Поле = i)

      ....

                     if (i == Размер массива)
                       {
                       pthread_attr_init(&attr);
                       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
      //db_storage_thread - Глобальная переменная                
                       pthread_create (&db_storage_thread, &attr,&my_proccess, (void *)packet);

                    pthread_detach(db_storage_thread);

                    packet = (pkt *)calloc(Размер массива,sizeof(pkt));
                    
                    i = 0;
                       }else{


                          i++;
                             }

                 } /* End while */

      ******************************************
      //my_proccess

      void my_proccess(pkt *packet)
      {

        for (i=0;i < Размер массива; i++)
             {
            
           ......

            Что то делаем с packet (сладываем каждый packet[i].поле в файл)
          
           ......
        
           }

      free(packet);
        
      }

      ******************************

      Происходит наверное именно так т.е. дочерний поток не успевает освободить память до того как основной ее заново выделит. Как такого избежать? Использовать realloc?

      • malloc/free in threads утечка памяти, !*! SaneK, 17:08 , 13-Май-03 (5)
        Забыл, pkt - глобальная
      • malloc/free in threads утечка памяти, !*! David, 18:22 , 13-Май-03 (6)
        realloc тут не поможет.

        самое лучшее решение - изменить дизайн программы, как уже советовал NL.

        Другое трудно предложить - трудно представить что может происходить, когда несколько потоков работают с одним куском памяти, один из них освобождает эту память, а другие при этом ничего не ведают. Очень странно, что программа вообще работает, не вылетая по segmentation fault.

      • malloc/free in threads утечка памяти, !*! Olej, 18:32 , 14-Май-03 (7)
        Было что-то такое...

        >void my_proccess(pkt *packet) {

        - вот здесь нужно было бы:
        1. заблокироваться на каком-то механизме синхронизации, напр. на критическрй секции (с вызывающей программой);
        2. сделать копию *packet - не указателя, а всей структуры...
        3. снять блокировку, и уже можно free ... уже не нужно.
        4. для всего этого лучше при запуске определить в attr повышенный приоритет потока...

        >
        >  for (i=0;i < Размер массива; i++)
        >       {
        >
        >     ......
        >
        >      Что то делаем с packet (сладываем
        >каждый packet[i].поле в файл)
        >
        >     ......
        >
        >     }
        >
        >free(packet);

        - а вот здесь хорошо бы посмотреть (проанализировать) код завершения free, она же не void ... вообще проверка всех кодов завершения, до уровня параноидальности ;-) - хорошая привычка.

        Хотя реализация эта вся - безусловно плохая.
        Почему вызывающая программа не могла бы создавать копию *packet для каждого порождаемого потока, например?


        • malloc/free in threads утечка памяти, !*! SaneK, 12:27 , 15-Май-03 (9)
          В том то и дело что блокироваться с вызывающем программой нельзя. Основной цикл (в котором потоки порождаются) должен продолжаться без остановки.

          >Почему вызывающая программа не могла бы создавать копию *packet для каждого порождаемого потока, например?
          А как это реализовать (без остановки основного цикла)в данном случае я что то не пойму.


          • malloc/free in threads утечка памяти, !*! Olej, 11:51 , 16-Май-03 (10)
            >В том то и дело что блокироваться с вызывающем программой нельзя. Основной
            >цикл (в котором потоки порождаются) должен продолжаться без остановки.

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

            Вопрос всегда в том - на сколько блокироваться? на 1мксек, 1мсек, 1сек... А дополнительное (ко времени создания thread-а) время копирования блока параметров ... вряд ли особо существенно.

            >>Почему вызывающая программа не могла бы создавать копию *packet для каждого порождаемого потока, например?
            >А как это реализовать (без остановки основного цикла)в данном случае я что то не пойму.

            Как-то так - в вызывающей программе:
            while(1) {
              .... //вот здесь каждый раз выделяется блок параметров
              pkt* packet = (pkt*)calloc(Размер массива,sizeof(pkt));
              // никаких глобальных переменных... и заполняется...
              pthread_create (&db_storage_thread, &attr,&my_proccess, (void *)packet);
              ...

            а в функции потока:
            void my_proccess( pkt* packet ) {
              ......
              Что то делаем с packet
              free( packet );
            }

            но ещё лучше - я бы сразу делал дубликат блока параметров - уничтожал переданный блок, а потом что-то делал с дубликатом:
            void my_proccess( pkt* packet ) {
              pkt dubl( *packet );
              free( packet );
              ......
              Что то делаем с dubl
            }

            Обр. вним. - это решение тоже упрощённое, и имеет дефекты синхронизации (об этом и обсуждалось в тех URL, которые я писал) - но оно уже гораздо лучше.

            • malloc/free in threads утечка памяти, !*! SaneK, 12:52 , 16-Май-03 (11)
              >но ещё лучше - я бы сразу делал дубликат блока параметров - уничтожал переданный блок, а потом что-то делал с дубликатом:
              >void my_proccess( pkt* packet ) {
              >  pkt dubl( *packet );
              >  free( packet );
              >  ......
              >  Что то делаем с dubl
              >}

              Спасибо! Вроде помогло. Но только один момент:

              не

              pkt dubl(*packet);

              а

              pkt *dubl=packet;

              Еще раз спасибо!

              • malloc/free in threads утечка памяти, !*! SaneK, 12:55 , 16-Май-03 (12)
                Вопрос в догонку. Если я вместо такой реализации массива сделаю линейный список, плюс в скорости получу?
                • malloc/free in threads утечка памяти, !*! Olej, 17:55 , 16-Май-03 (14)
                  >Вопрос в догонку. Если я вместо такой реализации массива сделаю линейный список,
                  >плюс в скорости получу?

                  Нет, получите "минус", достаточно значительный ... я думаю.
                  Смотрите STL - vector - вот с ним можете получить и динамичность, и скорость...
                  Но это - C++!.
                  Хотя gcc - до фени - вопрос вкуса юзера ;-)


              • malloc/free in threads утечка памяти, !*! Olej, 15:16 , 16-Май-03 (13)
                >>но ещё лучше - я бы сразу делал дубликат блока параметров - уничтожал переданный блок, а потом что-то делал с дубликатом:
                >>void my_proccess( pkt* packet ) {
                >>  pkt dubl( *packet );
                >>  free( packet );
                >>  ......
                >>  Что то делаем с dubl
                >>}
                >
                >Спасибо! Вроде помогло. Но только один момент:
                >
                >не
                >
                > pkt dubl(*packet);
                >

                >
                > pkt *dubl=packet;
                >
                >Еще раз спасибо!
                >

                Если у вас есть конструктор по-умолчанию для структуры pkt - а он всегда есть ... если вы не испортили сами, руками - то и 1-е - сработает.

                Правда ... подумалось ... это всё в терминологии C++, я в ней имел в виду.


  • malloc/free in threads утечка памяти, !*! NL, 11:30 , 08-Май-03 (3)
    1) лучше писать прогу так: трэд, который выделил себе блок памяти, его же и освобожддает, а не поручать free другим трэдам. Так проще  отследить, что откуда берется да и код становится понятнее и путаницы меньше.
    2) используй realloc в основном трэде и тогда в остальных трэдах free можно выкинуть
    • malloc/free in threads утечка памяти, !*! Olej, 19:25 , 14-Май-03 (8)
      >1) лучше писать прогу так: трэд, который выделил себе блок памяти, его
      >же и освобожддает, а не поручать free другим трэдам. Так проще
      > отследить, что откуда берется да и код становится понятнее и
      >путаницы меньше.

      С блоком параметров запуска thread (то, что показано в мсходном коде) - это обычно не проходит, особенно, если thread не join, да и там ... тягомутина. Так что эта задача: синхронизация доступа и разрушения блока параметров - совсем не такая частная, и возникает...

      Посмотрите здесь:
      http://qnx.org.ru/forum/viewtopic.php?topic=266&forum=4&star...
      http://qnx.org.ru/forum/viewtopic.php?topic=1376&forum=4
      - может на что натолкнёт...

  • malloc/free in threads утечка памяти, !*! Olej, 17:01 , 19-Май-03 (15)
    >  При запуске приложения запускается основной поток далее по возникновению какого
    >то события из этого потока запускаются другие потоки использующие одну глобальную
    >переменную, память под которую выделяется malloc'ом в основном потоке и освобождается
    >free в потоках которые запускаются из основного. Доступ к этой переменной
    >разделяется с помощью мьютексов. Вроде прога работает, все нормально, но вот
    >только память используемая ей все время растет (top'ом смотрю).

    Вот, нашёл случайно - детальное обсуждение синхронизации ровно для того частого случая, который обсуждается: выделение блока параметров и передача его detached thread, который его и освобождает:
    http://qnx.org.ru/forum/viewtopic.php?topic=928&forum=4





Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру