На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Рекурсивный поиск файлов заполняет не выгруженный пул памяти Си WINAPI , Рекурсивный поиск файлов заполняет не выгруженный пул памяти Си WINAPI
    Приветствую,джентельмены.
    Пытаюсь выполнить поиск файлов на локальном диске,включая файлы во всех каталогах.
    Использовал для этого примеры,которые можно найти в интернете.
    Файлы находит,с этим проблем нет.
    Но,как я заметил,сжирает постепенно память(примерно 400мб с заполненного диска в 100Гб,около 220000 файлов),заполняя не выгруженный пул памяти.
    Я предполагаю,проблема в инициализации переменных в начале кода и в самой рекурсии.
    Если найденный файл является директорией(папкой),функция вызывает сама себя,передавая в качестве аргумента найденную папку и снова,и снова.
    Если файл не является директорией,строка передаётся в другую функцию.
    Таким образом,вызывая саму себя(дубликат),функция создаются новые переменные в которые пишутся строки,а старые не выгружаются,так как функция не завершилась.И так с каждой папкой.
    Подскажите,пожалуйста,как можно избавится от этой проблемы.
    ExpandedWrap disabled
      DWORD WINAPI SearchFiles(LPVOID lpName)
      {
          LPTSTR lpszFileName = (LPTSTR)GlobalAlloc(GMEM_FIXED, 1024);//lpszFileName,path переменные,
          LPTSTR path         = (LPTSTR)GlobalAlloc(GMEM_FIXED, 1024);    //которые инициализируются
          ZeroMemory(lpszFileName, 1024);                                              //и не выгружаются
          ZeroMemory(path, 1024);
       
          lstrcpy(lpszFileName, lpName);
          lstrcpy(path, lpszFileName);
          lstrcat(path, "*.*");
       
          HANDLE hand;
          WIN32_FIND_DATA data_file;
          hand = FindFirstFile(path, &data_file);
       
          if (hand != INVALID_HANDLE_VALUE)
          {
              do
              {
                  if (!strncmp(data_file.cFileName, ".", 1) || !strncmp(data_file.cFileName, "..", 2))
                  {
                      continue;
                  }
                  if (data_file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                  {
                      lstrcpy(path, lpszFileName);
                      lstrcat(path, data_file.cFileName);
                      lstrcat(path, "\\");
       
                      if (!lstrcmpi(path, WinPathD) == 0) //WinPathD - папка windows
                      {
       
                          SearchFiles((LPVOID)path); //тут функция вызывает сама семя
                      }
                  }
                  else
                  {
       
                          lstrcpy(file, lpszFileName);    // file глобальная переменная типа LPTSTR
                          lstrcat(file, data_file.cFileName);
       
                          Thread(file);
                  }
              } while (FindNextFile(hand, &data_file) != 0);
          }
          FindClose(hand);
       
          GlobalFree(lpszFileName);
          GlobalFree(path);
       
          return 0;
      }
      Цитата Sherman @
      Но,как я заметил,сжирает постепенно память(примерно 400мб с заполненного диска в 100Гб,около 220000 файлов),заполняя не выгруженный пул памяти.

      220 тыс файлов?
      Я правильно понимаю, что ты так и создаёшь отдельный поток на каждый файл? Если да, то они, потоки, и жрут память.
        Цитата Sherman @
        Я предполагаю,проблема в инициализации переменных в начале кода и в самой рекурсии.

        Если не нравится рекурсивный поиск, сделай не рекурсивный.
        Сравни результаты и выбери то, что больше понравилось.
          Цитата Олег М @
          Я правильно понимаю, что ты так и создаёшь отдельный поток на каждый файл?

          Не на каждый,кол-во потоков ограниченно 10,когда их становится 10,функция ждёт их завершения и снова создаёт.

          Добавлено
          Цитата ЫукпШ @
          Если не нравится рекурсивный поиск, сделай не рекурсивный.

          К сожалению,я не знаю,как это сделать.Всё,что находил в интернете,связанно с рекурсией.
          Если только искать в одной конкретной папке,то без нее.
            Цитата Sherman @
            Не на каждый,кол-во потоков ограниченно 10,когда их становится 10,функция ждёт их завершения и снова создаёт.

            CloseHandle() делаешь для них?
            Покажт полный код
              Цитата Олег М @
              CloseHandle() делаешь для них?

              ExpandedWrap disabled
                                    if( memory(1) < 85 && // memory(1) %загрузки памяти
                                               ff < THREADS ) // THREADS = 10
                                    {
                                        hThreadF[ff] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, (LPVOID)rFile, 0, NULL);
                                    }
                                    else
                                    {
                                        printf("\r\n*************************************************************\r\n\r\n");
                 
                                        for(int i = 0; i < ff; i++)
                                            WaitForSingleObject(hThreadF[i], INFINITE);
                 
                                        for(int i = 0; i < ff; i++)
                                            CloseHandle(hThreadF[i]);
                 
                                        ff = 0;
                                    
                                        hThreadF[ff] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, (LPVOID)rFile, 0, NULL);
                                    }
                                    ff++;

              Цитата Олег М @
              Покажт полный код

              хорошо,сейчас всё переписываю,как напишу,скину.
                Цитата Олег М @

                Раз уж речь зашла о потоках,не могли бы вы мне подсказать,если я создаю поток
                ExpandedWrap disabled
                  hThreadF[ff] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, (LPVOID)rFile, 0, NULL);

                Он может создаться не сразу,точнее говоря,нужно время на его создание,при этом,переменная (LPVOID)rFile,которую я передаю в поток,после этой строчки,меняется.
                Эта переменная не является глобальной.
                Когда поток будет создан,функция Thread получит уже изменённую переменную или то,что именно этому потоку и передавалось?
                  Цитата Sherman @
                  Когда поток будет создан,функция Thread получит уже изменённую переменную или то,что именно этому потоку и передавалось?

                  Поток создаётся сразу, исполняется позже. Значение будет передано то, которое на момент вызова CreateThread. И если ты не удаляешь этот ресурс в вызывающем потоке, то всё будет нормально.
                    Цитата Олег М @
                    И если ты не удаляешь этот ресурс в вызывающем потоке, то всё будет нормально.

                    fFile пересодаётся,не означает ли это,что прежний fFile будет удалён?
                    ExpandedWrap disabled
                                  else
                                  {
                       
                                          LPTSTR fFile = (LPTSTR)GlobalAlloc(GMEM_FIXED, lstrlen(lpszFileName) + lstrlen(data_file.cFileName) + 1);
                                          assert(fFile);
                                          lstrcpy(fFile, lpszFileName);
                                          lstrcat(fFile, data_file.cFileName);
                       
                                          if( memory(1) < 85 &&
                                                     ff < THREADS )
                                          {
                                              hThreadF[ff] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, (LPVOID)fFile, 0, NULL);
                                          }
                                          else
                                          {
                                              printf("\r\n*********************************************************************\r\n\r\n");
                       
                                              for(int i = 0; i < ff; i++)
                                                  WaitForSingleObject(hThreadF[i], INFINITE);
                       
                                              for(int i = 0; i < ff; i++)
                                                  CloseHandle(hThreadF[i]);
                       
                                              ff = 0;
                                          
                                              hThreadF[ff] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, (LPVOID)fFile, 0, NULL);
                                          }
                                          ff++;
                                  }
                      Цитата Sherman @
                      fFile пересодаётся,не означает ли это,что прежний fFile будет удалён?

                      Нет, не будет. Здесь всё более-менее правильно

                      Добавлено
                      Надеюсь, в потоке ты делаешь для него GlobalFree?
                        Цитата Олег М @

                        Спасибо.
                        Как можно освободить память,выделяемую этой переменной?
                        ExpandedWrap disabled
                          LPTSTR fFile = (LPTSTR)GlobalAlloc(GMEM_FIXED, lstrlen(lpszFileName) + lstrlen(data_file.cFileName) + 1);

                        Я пытаюсь вызвать GlobalFree для LPVOID в функции потока Правильный ли это подход?
                        ExpandedWrap disabled
                          DWORD WINAPI Thread(LPVOID gfile) {
                              // UNREFERENCED_PARAMETER(gfile);
                           
                              LPTSTR nfile = (LPTSTR)GlobalAlloc(GMEM_FIXED, SizeBuf);
                              ZeroMemory(nfile, SizeBuf);
                              lstrcpy(nfile, (TCHAR*)gfile);
                              GlobalFree(gfile);
                              over++;
                           
                              printf("%d %s\r\n", over, nfile);
                              GlobalFree(nfile);
                              Sleep(8000);
                           
                              return 0;
                          }
                        Сообщение отредактировано: Sherman -
                          ExpandedWrap disabled
                            DWORD WINAPI Thread(LPVOID gfile) {
                                // UNREFERENCED_PARAMETER(gfile);
                             
                                over++;
                             
                                printf("%d %s\r\n", over, (LPCSTR)gfile);
                                GlobalFree(gfile);
                                Sleep(8000);
                             
                                return 0;
                            }
                            Цитата Sherman @
                            К сожалению,я не знаю,как это сделать.Всё,что находил в интернете,связанно с рекурсией.
                            Если только искать в одной конкретной папке,то без нее.

                            Алгоритм простой.
                            Заготовим 2 списка строк - один для директорий, другой для файлов.
                            Занесём начальную директорию (полный путь) в список директорий.
                            Дальше начинается основной алгоритм.
                            ---
                            1. Проверяем, наличие строк в списке директорий.
                            2. Если нет - работа окончена, в списке файлов результат поиска.
                            3. Если есть - извлекаем 1-ю по счёту строку из списка, будем искать в этой директории
                            - отдельно файлы, добавляя результат в список файлов (полные пути).
                            - отдельно директории, добавляя результат в список директорий (полные пути).
                            4. закончился поиск в текущей директории - переход к пункту 1.
                            Это всё.
                            ---
                            Результатом работы алгоритма является список строк имен файлов (полные пути).
                              Спасибо,большое.Я уже так сделал,вроде работает.
                              Попробую,как память себя ведёт.
                                Я проверил твою функцию на своём движке в подобной утилите (поиск совпадающих под контексту файлов). Она показала те же затраты, что и мой движок. И они гораздо скромнее: 168Мб на без малого миллионе файлов. Так что если где и утечка, то явно не в SearchFiles()
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0517 ]   [ 16 queries used ]   [ Generated: 29.03.24, 11:09 GMT ]