Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > C/C++: Системное программирование и WinAPI > Рекурсивный поиск файлов заполняет не выгруженный пул памяти Си WINAPI


Автор: Sherman 12.05.19, 17:14
Приветствую,джентельмены.
Пытаюсь выполнить поиск файлов на локальном диске,включая файлы во всех каталогах.
Использовал для этого примеры,которые можно найти в интернете.
Файлы находит,с этим проблем нет.
Но,как я заметил,сжирает постепенно память(примерно 400мб с заполненного диска в 100Гб,около 220000 файлов),заполняя не выгруженный пул памяти.
Я предполагаю,проблема в инициализации переменных в начале кода и в самой рекурсии.
Если найденный файл является директорией(папкой),функция вызывает сама себя,передавая в качестве аргумента найденную папку и снова,и снова.
Если файл не является директорией,строка передаётся в другую функцию.
Таким образом,вызывая саму себя(дубликат),функция создаются новые переменные в которые пишутся строки,а старые не выгружаются,так как функция не завершилась.И так с каждой папкой.
Подскажите,пожалуйста,как можно избавится от этой проблемы.
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    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;
    }

Автор: Олег М 13.05.19, 07:43
Цитата Sherman @
Но,как я заметил,сжирает постепенно память(примерно 400мб с заполненного диска в 100Гб,около 220000 файлов),заполняя не выгруженный пул памяти.

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

Автор: ЫукпШ 13.05.19, 09:35
Цитата Sherman @
Я предполагаю,проблема в инициализации переменных в начале кода и в самой рекурсии.

Если не нравится рекурсивный поиск, сделай не рекурсивный.
Сравни результаты и выбери то, что больше понравилось.

Автор: Sherman 13.05.19, 11:37
Цитата Олег М @
Я правильно понимаю, что ты так и создаёшь отдельный поток на каждый файл?

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

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

К сожалению,я не знаю,как это сделать.Всё,что находил в интернете,связанно с рекурсией.
Если только искать в одной конкретной папке,то без нее.

Автор: Олег М 13.05.19, 11:39
Цитата Sherman @
Не на каждый,кол-во потоков ограниченно 10,когда их становится 10,функция ждёт их завершения и снова создаёт.

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

Автор: Sherman 13.05.19, 11:47
Цитата Олег М @
CloseHandle() делаешь для них?

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
                        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++;

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

хорошо,сейчас всё переписываю,как напишу,скину.

Автор: Sherman 13.05.19, 12:26
Цитата Олег М @

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

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

Автор: Олег М 13.05.19, 12:34
Цитата Sherman @
Когда поток будет создан,функция Thread получит уже изменённую переменную или то,что именно этому потоку и передавалось?

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

Автор: Sherman 13.05.19, 12:42
Цитата Олег М @
И если ты не удаляешь этот ресурс в вызывающем потоке, то всё будет нормально.

fFile пересодаётся,не означает ли это,что прежний fFile будет удалён?
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
                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++;
                }

Автор: Олег М 13.05.19, 12:45
Цитата Sherman @
fFile пересодаётся,не означает ли это,что прежний fFile будет удалён?

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

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

Автор: Sherman 13.05.19, 12:53
Цитата Олег М @

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

Я пытаюсь вызвать GlobalFree для LPVOID в функции потока Правильный ли это подход?
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    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;
    }

Автор: Олег М 13.05.19, 12:57
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    DWORD WINAPI Thread(LPVOID gfile) {
        // UNREFERENCED_PARAMETER(gfile);
     
        over++;
     
        printf("%d %s\r\n", over, (LPCSTR)gfile);
        GlobalFree(gfile);
        Sleep(8000);
     
        return 0;
    }

Автор: ЫукпШ 13.05.19, 13:02
Цитата Sherman @
К сожалению,я не знаю,как это сделать.Всё,что находил в интернете,связанно с рекурсией.
Если только искать в одной конкретной папке,то без нее.

Алгоритм простой.
Заготовим 2 списка строк - один для директорий, другой для файлов.
Занесём начальную директорию (полный путь) в список директорий.
Дальше начинается основной алгоритм.
---
1. Проверяем, наличие строк в списке директорий.
2. Если нет - работа окончена, в списке файлов результат поиска.
3. Если есть - извлекаем 1-ю по счёту строку из списка, будем искать в этой директории
- отдельно файлы, добавляя результат в список файлов (полные пути).
- отдельно директории, добавляя результат в список директорий (полные пути).
4. закончился поиск в текущей директории - переход к пункту 1.
Это всё.
---
Результатом работы алгоритма является список строк имен файлов (полные пути).

Автор: Sherman 13.05.19, 13:11
Спасибо,большое.Я уже так сделал,вроде работает.
Попробую,как память себя ведёт.

Автор: Qraizer 13.05.19, 13:13
Я проверил твою функцию на своём движке в подобной утилите (поиск совпадающих под контексту файлов). Она показала те же затраты, что и мой движок. И они гораздо скромнее: 168Мб на без малого миллионе файлов. Так что если где и утечка, то явно не в SearchFiles()

Автор: Sherman 13.05.19, 13:23
Цитата Qraizer @
Так что если где и утечка, то явно не в SearchFiles()

Согласен.fFile была объявлена глобально.Думаю,проблема была в этой переменной.
Перенёс её в функцию и передаю как аргумент,там же выделяю память.
Перепишу и протестирую.
Спасибо,что проверили.

Добавлено
Цитата ЫукпШ @

Благодарю.Интересный подход.Обязательно попробую.

Автор: JoeUser 13.05.19, 14:02
Цитата Sherman @
Интересный подход

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

Автор: Qraizer 13.05.19, 15:00
Только не хард-линки, а соединения, да и то только для каталогов. Хотя для файлов тоже имеет смысл сканить, чтоб не обрабатывать дубликаты, но к ошибкам это-таки не приведёт.

P.S. Если уж заводить разговор за стратегически правильный код, то там много что учитывать надо. Нужно отсекать как минимум FILE_ATTRIBUTE_TEMPORARY и FILE_ATTRIBUTE_OFFLINE. Нужно пытаться зайти в очередной каталог и проверять успех, а то вдруг прав нет туда заглядывать, иначе тоже легко можно свалиться в бесконечный скан одного и того же каталога. И если речь о каком-то аналоге бэкапа, было бы неплохо хотя бы пробовать не обновлять время доступа к очередному файлу, чтоб не ломать статистику по частоте использования.

Автор: Sherman 13.05.19, 15:05
Цитата JoeUser @
Все почему-то помнят только про файлы и каталоги, но напрочь забывают по хард-линки.

Что-то вообще сложное... .Попробую изучить эту тему.Спасибо.

Добавлено
Есть вопрос по кол-ву потоков.
Пишу программку,которая будет искать все файлы на ПК,проверяя расширение файла.
Если расширение файла совпадает с тем,что я укажу,mp4 например,создаёт поток передавая функции потока строку,содержащую полный путь к файлу.
Функция потока,в свою очередь,копирует найденные файлы на внешний жёсткий,который я тоже укажу.
Для этого я использую функции WINAPI(CreateFile,CreateFileMapping,MapViewOfFile).
Какое кол=во потоков можно использовать,для этой задачи?
Пока я просто ищу файлы,передаю строки в потоки и там вывожу их в консоль.
Так же вывожу целое число,которое соответствует кол-ву переданных строк в функцию потока.
Но я заметил,что число файлов показывает разное,при одинаковых условиях.
Чем больше потоков,тем больше разница.
Пробовал от 2 до 5000 потоков.(в качестве эксперимента)
На 500 потоков разнице +-10,на 5000 около 100000 строк.

Автор: ЫукпШ 13.05.19, 17:12
Цитата Qraizer @
P.S. Если уж заводить разговор за стратегически правильный код, то там много что учитывать надо. Нужно отсекать как минимум FILE_ATTRIBUTE_TEMPORARY и FILE_ATTRIBUTE_OFFLINE.

я делал так:
Для файлов : FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE
Для директорий : FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_REPARSE_POINT
И конечно, проверка на ошибку "ERROR_ACCESS_DENIED".
Детали я точно не помню. Но ничего страшного с запретом доступа нет.
Перечислить такую директорию (убедиться в её наличии) можно,
а искать файлы внутри нельзя. Произойдёт ошибка и цикл завершиться, ничего
страшного. Следить за этой ошибкой полезно исключительно в информационном смысле,
для выдачи сообщения, что "зайти туда было запрещено".

Автор: Sherman 13.05.19, 17:29
Цитата ЫукпШ @
И конечно, проверка на ошибку "ERROR_ACCESS_DENIED".

Не подскажете,как сделать эту проверку?

Автор: Олег М 13.05.19, 17:34
Цитата Sherman @
Какое кол=во потоков можно использовать,для этой задачи?


Цитата Sherman @
Функция потока,в свою очередь,копирует найденные файлы на внешний жёсткий,который я тоже укажу.
Для этого я использую функции WINAPI(CreateFile,CreateFileMapping,MapViewOfFile).
Какое кол=во потоков можно использовать,для этой задачи?

Я ж тебе вроде писал, что достаточно трёх потоков. С тех пор ничего не изменилось.
Не работает функция в потоке _beginthreadex (сообщение #3798301)

Автор: JoeUser 13.05.19, 19:49
Цитата Qraizer @
Только не хард-линки, а соединения, да и то только для каталогов.

Ну я образно. Хотя ты прав недо-хардлинки :)

Цитата Sherman @
Что-то вообще сложное... .Попробую изучить эту тему.Спасибо.

Так это еще не все, не расслабляйся! :lol: Надо искать файлы, которых "в явном виде нет, а они есть". Я про NTFS-потоки, а-ля:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    echo file-1>file-1.txt
    echo secret-1>file-1.txt:secret-1.txt

Файл secret-1.txt в листинге dir не виден. Но он есть, и он - в потоке файла file-1.txt, и можно убедиться:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    notepad file-1.txt
    notepad file-1.txt:secret-1.txt

Автор: Sherman 13.05.19, 20:28
Цитата Олег М @
Я ж тебе вроде писал, что достаточно трёх потоков. С тех пор ничего не изменилось.

Да,я помню,но с тем способом вообще беда у меня.
Я даже нигде не встречах подобие того,что вы описали.

Добавлено
Цитата JoeUser @

:blink:

Автор: ЫукпШ 13.05.19, 23:01
Цитата Sherman @
Цитата ЫукпШ @
И конечно, проверка на ошибку "ERROR_ACCESS_DENIED".

Не подскажете,как сделать эту проверку?

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
     BOOL RetC=FALSE;
     // ...
               hFind = ::FindFirstFile(pTempName, &FindFileData);
               if(hFind == INVALID_HANDLE_VALUE) {RetC = FALSE;}
               else                              {RetC = TRUE; }
     //...
               RetC = ::FindNextFile(...);
     
     if(RetC == FALSE)
     {
       DWORD LE = ::GetLastError();
     
    // возможные результаты окончания
       if(LE == ERROR_NO_MORE_FILES)  {...}  // ERROR_NO_MORE_FILES = 18, больше файлов не осталось
       if(LE == ERROR_FILE_NOT_FOUND) {...}  // ERROR_FILE_NOT_FOUND = 2, файл не найден
       if(LE == ERROR_PATH_NOT_FOUND) {...}  // ERROR_PATH_NOT_FOUND = 3, path не найден
     
    // доступ запрещён
       if(LE == ERROR_ACCESS_DENIED) {...}
     
    // другое - совсем плохо
     }

Автор: Sherman 14.05.19, 00:29
Цитата ЫукпШ @

Большое, спасибо!

Автор: Олег М 14.05.19, 06:43
Цитата Sherman @
Да,я помню,но с тем способом вообще беда у меня.
Я даже нигде не встречах подобие того,что вы описали.

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

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

Автор: JoeUser 14.05.19, 12:18
Цитата Олег М @
Все эти хардлинки с атрибутами это вторичная проблема, не факт, что с ней столкнёшься.

Не правда твоя! :)

Берем системный диск любой современной версии винды и видим сразу же в корне соединение "Users" -> "Documents and Settings":

user posted image

Автор: Олег М 14.05.19, 12:38
Цитата JoeUser @
Не правда твоя!

Необязательно тестировать на Document and Settings.

Автор: JoeUser 14.05.19, 14:14
Точнее - лучше не сканить систем диск с корня, иначе сбудутся пророчества тяжёлых времён :-)

Автор: Sherman 14.05.19, 14:41
Цитата Олег М @
Лучше сосредоточиться на нём, а когда заработает как часы, тогда уже можно заняться и деталями.

Полностью согласен.На данный момент я и копирование не делаю.Занимаюсь только настройкой поиска и потоков.

Добавлено
Цитата Олег М @
А что встречал - как на каждый чих зафигачить поток, авось система сама разберётся?

Нет,не встречал.Но встречал программку,которая делала что-то подобное и делала это очень быстро,и потоков было с лихвой.
Вот только кода этой программки я не видел,да и её самой у меня уже нет.
Случайно наткнулся,не думал на тот момент,что сам заинтересуюсь.
Всё,что я пока делал,работает очень медленно.
Всё,что я знаю о той проге, это то,что она работает с большим количеством потоков и с WINAPI.
Пробовал выполнять копирование при помощи Си (FILE*) и WINAPI(CreateFile),заметил,что WINAPI работает намного быстрее.
Думаю я на верном пути.

Добавлено
Цитата JoeUser @
Берем системный диск любой современной версии винды и видим сразу же в корне соединение "User" -> "Documents and Settings":

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

Автор: JoeUser 14.05.19, 16:10
Цитата Sherman @
и потоков было с лихвой

Олег М в своих предыдущих сообщения был во многом прав по поводу потоков. А мое резюме - ты люто и бешено зациклен на многопоточности. Народная мудрость гласит "все хорошо в меру". И тут это как ни кстати - актуально!

Пример. Берем восми-ядерный проц. И запускаем сборку Цэ++ проекта. Сколько потоков выделить на сборку?
Скрытый текст
Тут сикретик. И мой ответ тамошний - в топах. Народ кагбэ одобяет.

А вот теперь подумай, у тебя простой скан диска. Сколько операций твой дисковый массив сможет сделать одновременно? Универсального ответа нет. Если это честный хардварный рэйд - он закэширует твои вызовы хорошо, но все равно выполнит их последовательно или псевдо-параллельно. Если это мамковый fake-рэйд, сделает тоже самое, но плюс к тому загрузит камень, к гадалке не ходи! Единственный вменяемый вариант - когда идет одновременный скан n-независимых дисков, сидящих на разных интерфейсах.

Резюме

1) Если какого-то трудного пересчета нет - не делай потоков больше, чем количество отдельных физических носителей
2) Не верю что 2-х поточная прога на 2-х винтовом рэйде сильно победит однопоточную (если вообще сможет) и не уступит 3-х поточной

ЗЫ: Если захочешь узнать три Закона Будды - пиши в личку.

Добавлено
Цитата Sherman @
Но в моём случае,это не не нужно и даже вредно.

Тебе виднее для твоего случая. Без вопросов :lol:

Автор: ЫукпШ 14.05.19, 19:55
Цитата JoeUser @
Цитата Олег М @
Все эти хардлинки с атрибутами это вторичная проблема, не факт, что с ней столкнёшься.

Не правда твоя! :)

Берем системный диск любой современной версии винды и видим сразу же в корне соединение "User" -> "Documents and Settings":

Не совсем понятно, о чём дискуссия..
У этой директории просто установлены атрибуты:
FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_REPARSE_POINT
(и конечно FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)
Если захочется специально проигнорировать объект с такими атрибутами
это можно сделать. И в результате игнорировать такую директорию для дальнейших действий.
Если поиск не фильтровать по атрибутам, директория будет найдена.

Автор: JoeUser 14.05.19, 20:53
ЫукпШ, да я к тому - что файловый носитель уже давно ушел от древовидной структуры.
И только упоротый гик пытается делать обход "дерева", не взирая на все увещевания.
Я кончил.

Автор: Qraizer 14.05.19, 21:28
Цитата ЫукпШ @
Если захочется специально проигнорировать объект с такими атрибутами ...
В отношении FILE_ATTRIBUTE_REPARSE_POINT мнение может быть двояким. С одной стороны, они являются ссылками на другие объекты, которые либо находятся вне рассматриваемой области тома, а то и вообще другого тома, либо и без учёта этой ссылки тоже будут обработаны. С другой же стороны, не зря же эта ссылка тут расположена, значит кому-то было нужно, чтобы та, другая, область (другого) тома вроде бы считалась как будто бы находящаяся тут. Так что этот аспект не абсолютен и вполне себе обсуждаем, и наличие этого атрибута у объекта целиком и полностью зависит от пользователя. Даже не автора программы. JoeUser же говорил о другом его аспекте: этот атрибут может иметь объект, ссылающийся на одного из своих родителей. И это уже куда серьёзней, так как его игнор ведёт к бесконечной петле. Попробуй его не игнорировать и при этом не допустить циклов. Это не так-то просто запрограммировать.
С другими атрибутами другая петрушка. FILE_ATTRIBUTE_TEMPORARY выставляется приложениями для объектов, которые являются порождениями реализаций их внутренних алгоритмов. Такие объекты используются ими временно, для внутренних нужд и не содержат полезной для пользователя информации. Игнорировать такие объекты сам бог велел, ибо зачем обрабатывать мусор?
FILE_ATTRIBUTE_OFFLINE говорит о том, что объект в данный момент недоступен, поэтому его обработка непосредственно сейчас может оказаться невозможной или потребовать от пользователя телодвижений, т.е. неких ручных операций, для обеспечения доступа к нему. Вряд ли пользователя это обрадует, тем более, что он всё равно, зная, что запускает приложения по обработке данных, должен был бы заранее озаботиться предоставлением доступа ко всем таким объектам, и тогда этот атрибут был бы с них уже снят. Да, он может об этом не подумать или просто забыть о парочке таких, однако останов программы, запущенной на ночь для длительной обработки в нерабочее время, в паузу поутру может обернуться неслабыми матюгами. Из-за одного объекта не были обработаны куча других, вполне нормальных. Поэтому будет хорошей практикой все такие объекты обходить, чтоб не тормозить себе работу, однако включить их отчёт о проделанной работе как о непроделанной.

Автор: Олег М 15.05.19, 06:20
Цитата Sherman @
Всё,что я пока делал,работает очень медленно.
Всё,что я знаю о той проге, это то,что она работает с большим количеством потоков и с WINAPI.

Думаю, первое вытекает из второго.
Скорее всего, она использует асинхронный ввод-вывод, виндовский, а тот, в свою очередь - пул потоков.

Автор: Sherman 15.05.19, 15:22
Цитата Олег М @
Скорее всего, она использует асинхронный ввод-вывод, виндовский, а тот, в свою очередь - пул потоков.

OVERLAPPED это то что мне нужно?
Вчера только наткнулся на эту "фишку".
Переодически веду всякие заметки по программированию в блокноте.Нашёл и о этой программке заметку.
Она использовала CreateFileW,CreateFileA,CreateFileMappingA,MapViewOfFile,UnmapViewOfFile,SetFilePointerEx,WriteFile,GlobalAlloc,GlobalFree,RtlZeroMemory,CreateThread,
По крайней мере,это было в листинге дис-ассамблера.
Здесь не случайно нет ReadFile.
По всей видимости,она проецировала файл(карту) в виртуальной памяти,читала карту блоками и писала в другой.
Если это делать,как вы писали,разделить эти процедуры по разным потокам,получается,нужно в одном потоке искать файлы,во-втором проецировать
файл и передавать в третий хедл CreateFileMappingA,в котором,в свою очередь,читать карту(MapViewOfFile) и писать в файл?

Автор: Олег М 15.05.19, 17:56
Цитата Sherman @
OVERLAPPED это то что мне нужно?

Нет. Сначала тебе нужно сделать то что я тебе рекомендовал, это самое простое, с чего надо начинать. Проецирование и т.п. - это следующий шаг, не стоит перескакивать.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)