На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Не работает функция в потоке _beginthreadex , Не работает функция в потоке _beginthreadex
    Пишу многопоточную программу для поиска файлов.
    Для создания потоков использую _beginthreadex.
    Но программа запускается и через некоторое время завершается(без ошибок),а должна выводить путь к файлам в консоль.
    Без создания потоков(при работе в основном потоке программы) всё работает,файлы находятся и выводятся.
    Подскажите,пожалуйста,в чём ошибка?
    Компилирую из консоли gcc main.c -o char -static -s -Wall -Wextra -Werror -W
    ExpandedWrap disabled
      #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;
      }
      Если я правильно отреверсил,что ты хотел написать, то 68-я строка абсолютно лишняя. Она пытается удалить память, которая ни разу не в хипе.
      Кроме того, переопределение MAX_PATH ничего тебе не даст. Ограничение на длину буфера в ANSI-функциях WinAPI является фундаментальным. Вроде бы можно это отключить в Win10 где-то в реестре, но подробностей я не знаю. Ограничения на MAX_PATH изначально лишены Unicode-функции WinAPI, только маршрут при этом надо начинать с L"\\?\"
        Цитата Qraizer @
        68-я строка абсолютно лишняя.

        Спасибо,исправлю.
        Но всё же,как быть с потоками?
        Я несколько раз пересматривал на microsoft, просмотрел с десяток примеров на форумах и блогах.
        Мой код,вроде,по феншую(что касается создания потоков).
        Но функция не выводит файлы,да и вообще не запускается.
        При этом (HANDLE)_beginthreadex не возвращает NULL.
        Как бы потоки созданы.
        Пробовал в 22 строку просто вписать типо printf("hello\r\n");
        И это не вывелось... .
          Цитата Sherman @
          Но функция не выводит файлы,да и вообще не запускается.

          Убери мьютекс, совсем. В этой задаче он не нужен.
            Цитата Олег М @
            Убери мьютекс, совсем. В этой задаче он не нужен.

            В этом примере,согласен.
            Оставил его по причине того,что на месте printf будут создаваться потоки функции копирования файла,а в ней будет изменяться глобальная переменная
            типа int(счётчик созданных потоков),после чего,разлочиваться.
            Сообщение отредактировано: Sherman -
              Цитата Sherman @
              В этом примере,согласен.
              Оставил его по причине того,что на месте printf будут создаваться потоки функции копирования файла,а в ней будет изменяться глобальная переменная

              Там он тоже не нужен. Ты используешь его для доступа к глобальным переменным, можно обойтись без них - передавай параметром в функцию потока не char *, а указатель на структуру.

              а вообще, начни с простого
              ExpandedWrap disabled
                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;
                }
                В конце функции потока SearchFiles2 была функция _endthreadex(0); заменил на return 0; всё заработало... .
                Спасибо за помощь,тему не закрываю,попробую из этого потока создавать потоки на каждый файл.
                Результаты доложу :D
                  Цитата Sherman @
                  В конце функции потока SearchFiles2 была функция _endthreadex(0); заменил на return 0; всё заработало... .


                  Вообще, вызов этой функций в конце потока вроде никак не должен влиять (хотя вызывать её не нужно).
                  Т.е. ты опять показал какой-то урезанный код?
                    Есть вопрос.
                    Я создаю поток и пишу его в HANDLE

                    И таких 10,например.
                    Когда их становится 10,жду завершения и обнуляю счётчик

                    Нужно ли мне закрывать HANDLE перед созданием новых потоков или просто они перепишутся?
                    ExpandedWrap disabled
                                
                      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);
                      }
                      Цитата Sherman @
                      Нужно ли мне закрывать HANDLE перед созданием новых потоков или просто они перепишутся?

                      Конечно нужно. Для каждого вызова _beginthreadex должен вызыватся ::CloseHandle, иначе будет нефиговая утечка ресурсов.
                        Цитата Олег М @
                        Т.е. ты опять показал какой-то урезанный код?

                        Нет,сам не понял как получилось.Сотни раз пишу,переписываю и вышло так,что здесь return NULL,а у меня это.
                        А код весь,что есть на данный момент.
                        Приступаю к написанию потоковой функции работы с найденными файлами.

                        Добавлено
                        Цитата Олег М @
                        Конечно нужно. Для каждого вызова _beginthreadex должен вызыватся ::CloseHandle, иначе будет нефиговая утечка ресурсов.

                        Понял,спасибо.

                        Добавлено
                        Цитата Олег М @
                        Вообще, вызов этой функций в конце потока вроде никак не должен влиять (хотя вызывать её не нужно).

                        "Поток, который создается с помощью _beginthreadex завершается путем вызова _endthreadex."
                        Написано на сайте microsoft, вот я и влепил.
                        Сообщение отредактировано: Sherman -
                          Спустя пару минут прогона 24 потоков функции,в которой записанные строки выводятся в консоль,выдало ошибку
                          "Код исключения: c0000024"
                          ExpandedWrap disabled
                            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;
                            }
                          Сообщение отредактировано: Sherman -
                            ExpandedWrap disabled
                                Имя события проблемы: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
                              Цитата Sherman @
                              Спустя пару минут прогона 24 потоков функции,в которой записанные строки выводятся в консоль,выдало ошибку
                              "Код исключения: c0000024"


                              Ты уверен, что у тебя все пути помещаются в MAX_PATH? Поставь проверку
                                Цитата Олег М @
                                Ты уверен, что у тебя все пути помещаются в MAX_PATH? Поставь проверку

                                Нет,не уверен.А если нет,могу ли я вписать 1024,например?
                                Не будет ли каракулей и т.п.?
                                Или нужно malloc юзать?
                                А как грамотно сделать проверку,strlen()?
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0408 ]   [ 17 queries used ]   [ Generated: 19.03.24, 11:55 GMT ]