Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.119.104.238] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Приветствую,джентельмены.
Пытаюсь выполнить поиск файлов на локальном диске,включая файлы во всех каталогах. Использовал для этого примеры,которые можно найти в интернете. Файлы находит,с этим проблем нет. Но,как я заметил,сжирает постепенно память(примерно 400мб с заполненного диска в 100Гб,около 220000 файлов),заполняя не выгруженный пул памяти. Я предполагаю,проблема в инициализации переменных в начале кода и в самой рекурсии. Если найденный файл является директорией(папкой),функция вызывает сама себя,передавая в качестве аргумента найденную папку и снова,и снова. Если файл не является директорией,строка передаётся в другую функцию. Таким образом,вызывая саму себя(дубликат),функция создаются новые переменные в которые пишутся строки,а старые не выгружаются,так как функция не завершилась.И так с каждой папкой. Подскажите,пожалуйста,как можно избавится от этой проблемы. 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; } |
Сообщ.
#2
,
|
|
|
Цитата Sherman @ Но,как я заметил,сжирает постепенно память(примерно 400мб с заполненного диска в 100Гб,около 220000 файлов),заполняя не выгруженный пул памяти. 220 тыс файлов? Я правильно понимаю, что ты так и создаёшь отдельный поток на каждый файл? Если да, то они, потоки, и жрут память. |
Сообщ.
#3
,
|
|
|
Цитата Sherman @ Я предполагаю,проблема в инициализации переменных в начале кода и в самой рекурсии. Если не нравится рекурсивный поиск, сделай не рекурсивный. Сравни результаты и выбери то, что больше понравилось. |
Сообщ.
#4
,
|
|
|
Цитата Олег М @ Я правильно понимаю, что ты так и создаёшь отдельный поток на каждый файл? Не на каждый,кол-во потоков ограниченно 10,когда их становится 10,функция ждёт их завершения и снова создаёт. Добавлено Цитата ЫукпШ @ Если не нравится рекурсивный поиск, сделай не рекурсивный. К сожалению,я не знаю,как это сделать.Всё,что находил в интернете,связанно с рекурсией. Если только искать в одной конкретной папке,то без нее. |
Сообщ.
#5
,
|
|
|
Цитата Sherman @ Не на каждый,кол-во потоков ограниченно 10,когда их становится 10,функция ждёт их завершения и снова создаёт. CloseHandle() делаешь для них? Покажт полный код |
Сообщ.
#6
,
|
|
|
Цитата Олег М @ CloseHandle() делаешь для них? 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++; Цитата Олег М @ Покажт полный код хорошо,сейчас всё переписываю,как напишу,скину. |
Сообщ.
#7
,
|
|
|
Цитата Олег М @ Раз уж речь зашла о потоках,не могли бы вы мне подсказать,если я создаю поток hThreadF[ff] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, (LPVOID)rFile, 0, NULL); Он может создаться не сразу,точнее говоря,нужно время на его создание,при этом,переменная (LPVOID)rFile,которую я передаю в поток,после этой строчки,меняется. Эта переменная не является глобальной. Когда поток будет создан,функция Thread получит уже изменённую переменную или то,что именно этому потоку и передавалось? |
Сообщ.
#8
,
|
|
|
Цитата Sherman @ Когда поток будет создан,функция Thread получит уже изменённую переменную или то,что именно этому потоку и передавалось? Поток создаётся сразу, исполняется позже. Значение будет передано то, которое на момент вызова CreateThread. И если ты не удаляешь этот ресурс в вызывающем потоке, то всё будет нормально. |
Сообщ.
#9
,
|
|
|
Цитата Олег М @ И если ты не удаляешь этот ресурс в вызывающем потоке, то всё будет нормально. fFile пересодаётся,не означает ли это,что прежний fFile будет удалён? 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++; } |
Сообщ.
#10
,
|
|
|
Цитата Sherman @ fFile пересодаётся,не означает ли это,что прежний fFile будет удалён? Нет, не будет. Здесь всё более-менее правильно Добавлено Надеюсь, в потоке ты делаешь для него GlobalFree? |
Сообщ.
#11
,
|
|
|
Цитата Олег М @ Спасибо. Как можно освободить память,выделяемую этой переменной? LPTSTR fFile = (LPTSTR)GlobalAlloc(GMEM_FIXED, lstrlen(lpszFileName) + lstrlen(data_file.cFileName) + 1); Я пытаюсь вызвать GlobalFree для LPVOID в функции потока Правильный ли это подход? 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; } |
Сообщ.
#12
,
|
|
|
DWORD WINAPI Thread(LPVOID gfile) { // UNREFERENCED_PARAMETER(gfile); over++; printf("%d %s\r\n", over, (LPCSTR)gfile); GlobalFree(gfile); Sleep(8000); return 0; } |
Сообщ.
#13
,
|
|
|
Цитата Sherman @ К сожалению,я не знаю,как это сделать.Всё,что находил в интернете,связанно с рекурсией. Если только искать в одной конкретной папке,то без нее. Алгоритм простой. Заготовим 2 списка строк - один для директорий, другой для файлов. Занесём начальную директорию (полный путь) в список директорий. Дальше начинается основной алгоритм. --- 1. Проверяем, наличие строк в списке директорий. 2. Если нет - работа окончена, в списке файлов результат поиска. 3. Если есть - извлекаем 1-ю по счёту строку из списка, будем искать в этой директории - отдельно файлы, добавляя результат в список файлов (полные пути). - отдельно директории, добавляя результат в список директорий (полные пути). 4. закончился поиск в текущей директории - переход к пункту 1. Это всё. --- Результатом работы алгоритма является список строк имен файлов (полные пути). |
Сообщ.
#14
,
|
|
|
Спасибо,большое.Я уже так сделал,вроде работает.
Попробую,как память себя ведёт. |
Сообщ.
#15
,
|
|
|
Я проверил твою функцию на своём движке в подобной утилите (поиск совпадающих под контексту файлов). Она показала те же затраты, что и мой движок. И они гораздо скромнее: 168Мб на без малого миллионе файлов. Так что если где и утечка, то явно не в SearchFiles()
|