Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[52.15.63.145] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Пишу многопоточную программу для поиска файлов.
Для создания потоков использую _beginthreadex. Но программа запускается и через некоторое время завершается(без ошибок),а должна выводить путь к файлам в консоль. Без создания потоков(при работе в основном потоке программы) всё работает,файлы находятся и выводятся. Подскажите,пожалуйста,в чём ошибка? Компилирую из консоли gcc main.c -o char -static -s -Wall -Wextra -Werror -W #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <sys/stat.h> #include <assert.h> #include <signal.h> #include <unistd.h> #ifndef MAX_PATH #define MAX_PATH 1024 #endif HANDLE hMutex; int find_file = 0, drive = 0; unsigned __stdcall SearchFiles2(void* lpszFile) { CONST char *lpszFileName = (CONST char *)lpszFile; char path[MAX_PATH] = { 0 }; char temp[MAX_PATH] = { 0 }; strcpy(path, lpszFileName); strcat(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) { strcpy(path, lpszFileName); strcat(path, data_file.cFileName); strcat(path, "\\"); strcpy(temp, path); strlwr(temp); if (!lstrcmp(temp, "c:\\windows\\") == 0) { SearchFiles(path); } } else { WaitForSingleObject(hMutex, INFINITE); char *file = (char*)malloc(strlen(lpszFileName) + strlen(data_file.cFileName) + 64); assert(file); strcpy(file, lpszFileName); strcat(file, data_file.cFileName); printf("%s\r\n", file); ReleaseMutex(hMutex); } } while (FindNextFile(hand, &data_file) != 0); } FindClose(hand); free(lpszFile); return NULL; } int main(void) { char buf[BUF_PATH] = { 0 }; char drives[32][10] = { 0 }; GetLogicalDriveStringsA(sizeof(buf), buf); for (char *s = buf; *s; s += strlen(s) + 1) { strcpy(drives[drive], s); drive++; } HANDLE hThreads[drive]; hMutex = CreateMutex(NULL, FALSE, NULL); for(int i = 0; i < drive; i++) { hThreads[i] = (HANDLE)_beginthreadex(NULL, 0, &SearchFiles2, (void *)drives[i], 0, NULL); if(NULL == hThreads[i]) printf("Failed to create thread.\r\n"); } WaitForMultipleObjects(drive, hThreads, TRUE, INFINITE); for(int i = 0; i < drive; i++) CloseHandle(hThreads[i]); CloseHandle(hMutex); return 0; } |
Сообщ.
#2
,
|
|
|
Если я правильно отреверсил,что ты хотел написать, то 68-я строка абсолютно лишняя. Она пытается удалить память, которая ни разу не в хипе.
Кроме того, переопределение MAX_PATH ничего тебе не даст. Ограничение на длину буфера в ANSI-функциях WinAPI является фундаментальным. Вроде бы можно это отключить в Win10 где-то в реестре, но подробностей я не знаю. Ограничения на MAX_PATH изначально лишены Unicode-функции WinAPI, только маршрут при этом надо начинать с L"\\?\" |
Сообщ.
#3
,
|
|
|
Цитата Qraizer @ 68-я строка абсолютно лишняя. Спасибо,исправлю. Но всё же,как быть с потоками? Я несколько раз пересматривал на microsoft, просмотрел с десяток примеров на форумах и блогах. Мой код,вроде,по феншую(что касается создания потоков). Но функция не выводит файлы,да и вообще не запускается. При этом (HANDLE)_beginthreadex не возвращает NULL. Как бы потоки созданы. Пробовал в 22 строку просто вписать типо printf("hello\r\n"); И это не вывелось... . |
Сообщ.
#4
,
|
|
|
Цитата Sherman @ Но функция не выводит файлы,да и вообще не запускается. Убери мьютекс, совсем. В этой задаче он не нужен. |
Сообщ.
#5
,
|
|
|
Цитата Олег М @ Убери мьютекс, совсем. В этой задаче он не нужен. В этом примере,согласен. Оставил его по причине того,что на месте printf будут создаваться потоки функции копирования файла,а в ней будет изменяться глобальная переменная типа int(счётчик созданных потоков),после чего,разлочиваться. |
Сообщ.
#6
,
|
|
|
Цитата Sherman @ В этом примере,согласен. Оставил его по причине того,что на месте printf будут создаваться потоки функции копирования файла,а в ней будет изменяться глобальная переменная Там он тоже не нужен. Ты используешь его для доступа к глобальным переменным, можно обойтись без них - передавай параметром в функцию потока не char *, а указатель на структуру. а вообще, начни с простого unsigned __stdcall SearchFiles2(void* lpszFile) { printf("start thread\n"); .......................... if (hand != INVALID_HANDLE_VALUE) { do { printf("%s\n", data_file.cFileName); } while (FindNextFile(hand, &data_file) != 0); } FindClose(hand); free(lpszFile); printf("stop thread\n"); return NULL; } |
Сообщ.
#7
,
|
|
|
В конце функции потока SearchFiles2 была функция _endthreadex(0); заменил на return 0; всё заработало... .
Спасибо за помощь,тему не закрываю,попробую из этого потока создавать потоки на каждый файл. Результаты доложу |
Сообщ.
#8
,
|
|
|
Цитата Sherman @ В конце функции потока SearchFiles2 была функция _endthreadex(0); заменил на return 0; всё заработало... . Вообще, вызов этой функций в конце потока вроде никак не должен влиять (хотя вызывать её не нужно). Т.е. ты опять показал какой-то урезанный код? |
Сообщ.
#9
,
|
|
|
Есть вопрос.
Я создаю поток и пишу его в HANDLE И таких 10,например. Когда их становится 10,жду завершения и обнуляю счётчик Нужно ли мне закрывать HANDLE перед созданием новых потоков или просто они перепишутся? if( memory(1) < 86 && // memory(1) возвращает целое число,равное % загрузки памяти find_file < THREADS_NUMBER ) // THREADS_NUMBER 10 потоков, find_file плюсуется в функции потока { hFileThreads[find_file] = (HANDLE)_beginthreadex(NULL, 0, &Thread, (void *)file, 0, NULL); } else { WaitForMultipleObjects(find_file, hFileThreads, TRUE, INFINITE); find_file = 0; hFileThreads[find_file] = (HANDLE)_beginthreadex(NULL, 0, &Thread, (void *)file, 0, NULL); } |
Сообщ.
#10
,
|
|
|
Цитата Sherman @ Нужно ли мне закрывать HANDLE перед созданием новых потоков или просто они перепишутся? Конечно нужно. Для каждого вызова _beginthreadex должен вызыватся ::CloseHandle, иначе будет нефиговая утечка ресурсов. |
Сообщ.
#11
,
|
|
|
Цитата Олег М @ Т.е. ты опять показал какой-то урезанный код? Нет,сам не понял как получилось.Сотни раз пишу,переписываю и вышло так,что здесь return NULL,а у меня это. А код весь,что есть на данный момент. Приступаю к написанию потоковой функции работы с найденными файлами. Добавлено Цитата Олег М @ Конечно нужно. Для каждого вызова _beginthreadex должен вызыватся ::CloseHandle, иначе будет нефиговая утечка ресурсов. Понял,спасибо. Добавлено Цитата Олег М @ Вообще, вызов этой функций в конце потока вроде никак не должен влиять (хотя вызывать её не нужно). "Поток, который создается с помощью _beginthreadex завершается путем вызова _endthreadex." Написано на сайте microsoft, вот я и влепил. |
Сообщ.
#12
,
|
|
|
Спустя пару минут прогона 24 потоков функции,в которой записанные строки выводятся в консоль,выдало ошибку
"Код исключения: c0000024" unsigned __stdcall Thread(void * ffile) { char fille[MAX_PATH] = { 0 }; strcpy(fille, (CONST char *)ffile); free(ffile); find_file++; ReleaseMutex(hMutex); printf("%s\r\n", fille); Sleep(find_file * 5L); //небольшая задержка,которая увеличивается,как бы имитация какой-то работы с файлами разного объёма. return 0; } |
Сообщ.
#13
,
|
|
|
Имя события проблемы:APPCRASH Имя приложения:char.exe Версия приложения:0.0.0.0 Отметка времени приложения:5cd0387a Имя модуля с ошибкой:ntdll.dll Версия модуля с ошибкой:6.3.9600.18821 Отметка времени модуля с ошибкой:59ba8666 Код исключения:c0000024 Смещение исключения:0007d313 Версия ОС:6.3.9600.2.0.0.768.100 Код языка:1049 |
Сообщ.
#14
,
|
|
|
Цитата Sherman @ Спустя пару минут прогона 24 потоков функции,в которой записанные строки выводятся в консоль,выдало ошибку "Код исключения: c0000024" Ты уверен, что у тебя все пути помещаются в MAX_PATH? Поставь проверку |
Сообщ.
#15
,
|
|
|
Цитата Олег М @ Ты уверен, что у тебя все пути помещаются в MAX_PATH? Поставь проверку Нет,не уверен.А если нет,могу ли я вписать 1024,например? Не будет ли каракулей и т.п.? Или нужно malloc юзать? А как грамотно сделать проверку,strlen()? |