На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> FILE * чтение,запись. Многопоточность. , FILE * чтение,запись. Многопоточность.
    Всем привет.
    Пишу программку на Си только под Windows.Она ищет все файлы на диске по маске ,"*.тхт"например,найдя файл,создаёт поток pthread в котором вызывает функцию и передаёт ей в ,качестве аргумента,найденный файл и так далее,пока не достигнет заданного ограничения потоком.
    По достижению,ждёт завершения потоков и продолжает передачу новых найденных файлов.
    Функция в потоке,в свою очередь,работает с этими файлами,а точнее копирует их на другой диск открывая файл и читая байты в заданный буфер BYTE,а от туда в новый файл.
    Всё хорошо,когда файлов либо один,либо с десяток,при условии,что они не большого размера(который буфер может прочитать за один цикл).
    Но если их много,в одном из потоков,цикл чтения и записи становится бесконечным,соответственно,программа стоит на месте(не зависает и не выдаёт ошибку),цикл вращается - поток не завершается.При этом программа перестаёт читать и писать, нагрузка на память вовсе пропадает,а ЦП наоборот,сильно возрастает,за счёт огромного кол-ва бесконечных циклов.
    Даже если файл большой,но он один(= один поток),чтение и запись проходит успешно,поток завершается.
    file2 новый файл(копия file1 на другом диске) который я создаю.Да,в этом примере вывод написан не корректно.
    Получается,что открывается для записи один и тот же файл.Но это не так.Просто я упростил этот пример.Прошу прощения за путаницу.
    Каждому файлу,свой новый файл.
    Смысл в том,что программа ищет на всём диске все файлы txt и копирует их на другой диск.
    1 файл = 1 поток pthread. Ограничение в 4 потока одновременно.Когда создаётся 4 потока, вызывается pthread_join для каждого созданного потока.
    Потом счётчик обнуляется и всё по новой,только уже с новыми файлами.
    В чём проблема понять никак не могу.
    Помогите найти ошибку,пожалуйста.

    Код работает в 2 случаях:
    1.Если ограничить кол-во потоков в 1,соответственно копирование происходит в 1 поток и это не то,что нужно.
    2.Если убрать цикл while(!feof (in)), но в таком случае нужно целиком грузить файл в память,что не выход из положения,так как это прототип программы
    и ,вполне возможно,нужно будет копировать увесистые видео файлы и jpeg,ну или ещё что.

    memory(1) - возвращает целое число равное проценту загруженности памяти.
    find_file - целое число типа int,счётчик файлов.
    ExpandedWrap disabled
      #include <stdio.h>
      #include <stdlib.h>
      #include <errno.h>
       
      void *CopyMyFile(void *file)
      {
          FILE *in = fopen(file,"rb"), *out = fopen(file2,"wb");
          if (in == NULL || out == NULL) {
             perror (file);
             return NULL;
          }
          rewind(out);
       
          unsigned long int buf = 1e+7;
          
          BYTE *buffer = 0;
          if ((buffer = (BYTE *)malloc(buf *sizeof(BYTE)))==NULL)
          {
              printf("err buffer %s\r\n", strerror(errno));
              fclose(in);
              fclose(out);
              return NULL;
          }
       
          while(!feof (in)) //тут возникает бесконечный цикл,при работе в более чем один поток
          {
              DWORD Len = fread(buffer, sizeof(BYTE), buf, in);
       
              fwrite(buffer, sizeof(BYTE), Len, out);
          }
          free(buffer);
          fclose(in);
          fclose(out);
       
          return NULL;
      }
       
      BOOL logFile(char *file)
      {    
          if( memory(1) < 86 &&
             find_file < 4 )
          {
              pthread_create(&threadslogFile[find_file], NULL, CopyMyFile, (void *)file);
              find_file++;
          }
          else
          {
              for(int j = 0; j < find_file; j++)
              {
                  pthread_join(threadslogFile[j], NULL);
              }
              find_file = 0;
       
              pthread_create(&threadslogFile[find_file], NULL, CopyMyFile, (void *)file);
              find_file++;
          }
       
          return TRUE;
      }
      Ввиду того, что я не нашёл критических ошибок в коде и, построив на его основе пример, не обнаружил проблемы, могу заключить, что что-то из (или даже несколько):
      • твоя реализация pthread крива; я взял с гитхаба и собрал прям на месте, работает;
      • приложение не многопоточное; проверь, что используешь что-то типа -MT компилятору; если нет, то stdio.h тупо попадает в race condition;
      • твой код перебора файлов сбоит, и несколько потоков принимают один и тот же файл; как результат fread() получает ошибку доступа.
      Если последнее, то зацикливание на while(!feof()) объясняется естественно: это не конец файла, но и прочитать ничего нельзя из-за состояния ошибки. Добавь ferror() в цикл, узнаешь наверняка.
        Цитата Qraizer @
        [*]приложение не многопоточное; проверь, что используешь что-то типа -MT компилятору; если нет, то stdio.h тупо попадает в race condition;

        Спасибо за ответ.
        Компилирую MinGW gcc main.c -o copy -static -s -Wall -Wextra -Werror -W -lpthread
          Цитата Sherman @

          Добавил printf для вывода текста строки из функции потока.Не один файл не повторяется.И всё же проблема осталась.
          Как будто в цикле не может определить конец файла.Но при этом не происходит не чтения не запись.
          Скорость чтения с диска 0 .
          Прочитывает пачку файлов и на 1-2х из низ зацикливается.
            Вот не уверен, что мингву научили позикс-ниткам. До сих пор был инфа, что полноценной поддержки pthread ещё нет, и сами её контрибуторы рекомендуют VS-ную реализацию типа там _beginthreadex() etc, т.к. мигва использует обычные визуальные библиотеки. Попробуй-таки вот эту реализацию. У меня по крайней мере она собралась влёгкую. Для VC2017, правда, но для MinGW там тоже есть сценарии конфигурации и сборки.
            Сообщение отредактировано: Qraizer -
              Цитата Qraizer @

              Так без цикла whie потоки работают.
              Ставлю ограничение на 100 потоков,работает на ура.
              Но это не вариант,память не резиновая))
              Пробовал с CreatyThread WIN API,было то же самое.
                Цитата Sherman @
                Получается,что открывается для записи один и тот же файл.Но это не так.Просто я упростил этот пример.Прошу прощения за путаницу.

                Покажи полный код, этот что-то слишком упрощён.
                  Цитата Sherman @
                  Так без цикла whie потоки работают.
                  Это лишь значит, что ОС успешно избегает race condition в своих функциях ReadFile()/WriteFile(). Ну, как бы сомнений и не было. При единственном fread()/fwrite() на каждый файл, возможно, что и stdio не попадёт на race condition в своём коде. Пока всё говорит о том, что к твоей программе линкуется немногопоточная RTL, что вызывает коллизии общих данных библиотеки ввода/вывода. Ну или почему-то происходят ошибки чтения, о которых ты не знаешь, потому что не контролируешь ferror()

                  Добавлено
                  Цитата Sherman @
                  Пробовал с CreatyThread WIN API,было то же самое.
                  К слову ещё. Не уверен, что -lpthread достаточно. МинГВу особо и не юзал, а в gcc это означает лишь линковку с библиотекой pthread. Ну ок, прилинкуется, будут тебе потоки. Что-то мне подсказывает, что это не означает автоматически, что вместо однопоточной libstdc должна использоваться многопоточная. CreateThread() и K° тебе не помогут, они тут совершенно не причём. Просто подумай капельку: у тебя есть две нитки, которые вдруг внезапно одновременно решили сделать тебе printf("Hello, multithreaded world!\n"). Представил? Усугублю: представь, что каждая из ниток выполнила запись в свой уникальный файл, но у одной из них тут внезапно эррор; какое значение будет у errno?
                  Сообщение отредактировано: Qraizer -
                    Qraizer, на сколько я знаю - MinGW64 поставляется в 2-х видах реализации потоков: POSIX и winpthreads. Первая более тормозная, но обеспечивает на 100% все фичи многопоточности, декларированной в С++11 и выше. Вторая - типа ускоренная, но все фичи многопоточности С++11 не реализует. А вот на счет голого Си - инфы мало. Просьба к тебе, как к гуру Си и иже с ним... Разберись и проясни ситуацию. Тебе это обернется более "меньшей кровью" ввиду большего опыта. А профит для форума и форумчан будет просто адовый! Плис-плис!!!
                      Цитата Qraizer @
                      но у одной из них тут внезапно эррор; какое значение будет у errno?

                      Я совсем не давно начал заниматься программированием и затрудняюсь вам ответить.

                      Добавлено
                      Цитата Олег М @
                      Покажи полный код, этот что-то слишком упрощён.

                      Хорошо,но сейчас,ввиду множественных переработок,код такой,что и я не всегда понимаю.
                      Дайте немного времени,я перепишу в более вразуметельной форме и выложу.
                        Компиляция: gcc copy.c -o copy -static -s -Wall -Wextra -Werror -W -lpthread
                        Вот полный код:
                        ExpandedWrap disabled
                          #include <stdio.h>
                          #include <stdlib.h>
                          #include <windows.h>
                          #include <sys/stat.h>
                          #include <assert.h>
                          #include <signal.h>
                          #include <unistd.h>
                          #include <pthread.h>
                           
                          #ifndef MAX_PATH
                          #define MAX_PATH 1024
                          #endif
                           
                          #define BLOCK_SIZE 3.2e+7
                          #define THREADS_NUMBER 10
                           
                          int find_file = 0, drive = 0;
                           
                          char DriveS[MAX_PATH] = { 0 };
                          char TypeFile[MAX_PATH] = { 0 };
                          char NameFile[MAX_PATH] = { 0 };
                           
                          pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
                          pthread_cond_t cond;
                           
                          pthread_t *threadslogFile = { 0 };
                          pthread_t *threadsBuffer = { 0 };
                           
                          void * SearchFiles(void * lpszFile);
                           
                          int main(void)
                          {
                              //здесь в консоль вводим имя диска,на который будем копировать
                              //и тип искомых файлов.
                              //пока статично задаю.
                              strcpy(DriveS, "E:\\");
                              strcpy(TypeFile, "txt");
                           
                              threadslogFile = (pthread_t*) malloc(100 * sizeof(pthread_t));
                              assert(threadslogFile);
                              threadsBuffer = (pthread_t*) malloc(32 * sizeof(pthread_t));
                              assert(threadsBuffer);
                           
                              char buf[120] = { 0 };
                              char drives[32][10] = { 0 };
                              GetLogicalDriveStringsA(sizeof(buf), buf);
                              for (char *s = buf; *s; s += strlen(s) + 1)
                              {
                                  if (!strcmp(s, DriveS) == 0)
                                  {
                                      strcpy(drives[drive], s);
                                      drive++;
                                  }
                              }
                           
                              for(int i = 0; i < drive; i++)
                                  pthread_create(&threadsBuffer[i], NULL, SearchFiles, (void*)drives[i]);
                           
                              for(int i = 0; i < drive; i++)
                                  pthread_join(threadsBuffer[i], NULL);
                           
                              for(int j = 0; j < find_file; j++)
                                  pthread_join(threadslogFile[j], NULL);
                           
                              free(threadsBuffer);
                              free(threadslogFile);
                           
                              printf("\r\n\r\nend");
                           
                              getchar();
                              return 0;
                          }
                           
                          unsigned long long memory(int mod)
                          {
                              MEMORYSTATUS theStatus;
                              ZeroMemory(&theStatus, sizeof(theStatus));
                              theStatus.dwLength = sizeof(theStatus);
                              GlobalMemoryStatus(&theStatus);
                           
                              if(mod == 1)
                              {
                                  return theStatus.dwMemoryLoad; // %load
                              }
                           
                              if(mod == 2)
                              {
                                  return (theStatus.dwAvailPhys); // avail memory byte
                              }
                           
                              if(mod == 3)
                              {
                                  return (theStatus.dwTotalPhys); // total memory byte
                              }
                           
                              return 0;
                          }
                           
                          unsigned long int fsize(const char *filename)
                          {
                              struct stat st;
                           
                              if (stat(filename, &st) == 0)
                                  return st.st_size;
                           
                              return -1;
                          }
                           
                          void * CopyMyFile(void * ffile)
                          {
                              char file[MAX_PATH] = { 0 };
                              strcpy(file, (CONST char *)ffile);
                              free(ffile);
                           
                              char new_file[MAX_PATH] = { 0 };
                              strcpy(new_file, DriveS);
                              strcat(new_file, NameFile);
                           
                              find_file++;
                           
                              printf("%s\r\n", NameFile);
                           
                              pthread_mutex_unlock(&lock);
                           
                              FILE *in = fopen(file,"rb"), *out = fopen(new_file,"wb");
                              if (in == NULL || out == NULL) {
                                 perror (file);
                                 return NULL;
                              }
                              rewind(out);
                           
                              unsigned long int buf = 0;
                              unsigned long int file_size = fsize(new_file);
                           
                              if(file_size < BLOCK_SIZE)
                                  buf = (file_size + 64);
                              else
                                  buf = BLOCK_SIZE;
                           
                              BYTE *buffer = 0;
                              if ((buffer = (BYTE *)malloc(buf *sizeof(BYTE)))==NULL)
                              {
                                  printf("Buffer %s\r\n", strerror(errno));
                                  fclose(in);
                                  fclose(out);
                                  return NULL;
                              }
                           
                              while(!feof (in)) //тут возникает бесконечный цикл,при работе в более чем один поток
                              {
                                  DWORD Len = fread(buffer, sizeof(BYTE), buf, in);
                           
                                  fwrite(buffer, sizeof(BYTE), Len, out);
                              }
                              free(buffer);
                              fclose(in);
                              fclose(out);
                           
                              if ( in )
                                  fclose( in );
                              if ( out )
                                  fclose( out );
                           
                              DWORD dwAttrNewFile = GetFileAttributes(file);
                              SetFileAttributes(new_file, dwAttrNewFile);
                           
                             return NULL;
                          }
                           
                          char *CheckType (register const char *s, int c)
                          {
                            char *rtnval = "0";
                           
                            do {
                              if (*s == c)
                                rtnval = (char*) s;
                            } while (*s++);
                            return (rtnval + 1);
                          }
                           
                          void * SearchFiles(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
                                      {
                                          char * type = CheckType(data_file.cFileName,'.');
                           
                                          if(strcmp(type, TypeFile) == 0 )
                                          {
                                              pthread_mutex_lock(&lock);
                           
                                              char *file = (char*)malloc(strlen(lpszFileName) + strlen(data_file.cFileName) + 64);
                                              assert(file);
                                            
                                              strcpy(file, lpszFileName);
                                              strcat(file, data_file.cFileName);
                                            
                                              strcpy(NameFile,data_file.cFileName);
                                                                
                                              if( memory(1) < 86 &&
                                                  find_file < THREADS_NUMBER )
                                              {
                                                  pthread_create(&threadslogFile[find_file], NULL, &CopyMyFile, (void *)file);
                                              }
                                              else
                                              {
                                                  for(int j = 0; j < find_file; j++)
                                                  {
                                                      pthread_join(threadslogFile[j], NULL);
                                                  }
                                                  find_file = 0;
                                              
                                                  pthread_create(&threadslogFile[find_file], NULL, &CopyMyFile, (void *)file);
                                              }
                                          }
                                      }
                                  } while (FindNextFile(hand, &data_file) != 0);
                              }
                              FindClose(hand);
                              free(lpszFile);
                           
                              return NULL;
                          }


                        Добавлено
                        Если не затруднит,попробуйте скомпилировать и протестировать.
                          Цитата Sherman @
                          Код работает в 2 случаях:
                          1.Если ограничить кол-во потоков в 1,соответственно копирование происходит в 1 поток и это не то,что нужно.
                          2.Если убрать цикл while(!feof (in)),

                          я попробовал сделать то, что и ты, и у меня всё получилось.
                          MinGw студия у меня какая-то очень старая, и текст твой я копировал
                          конечно не весь, а кусками.
                          Число файлов и число потоков можно менять и проблем не возникало.
                          Получилось так:
                          Скрытый текст

                          ExpandedWrap disabled
                            // --------------------------------------------------------------------------
                            //
                            // file HelloWorld.cpp 22.12.2012, 05.05.2019
                            //
                            // --------------------------------------------------------------------------
                            #include "stdafx.h"
                            #include <pthread.h>
                            // --------------------------------------------------------------------------
                            using namespace std;
                            // --------------------------------------------------------------------------
                            #define ERROR_CREATE_THREAD -11
                            #define ERROR_JOIN_THREAD   -12
                            #define SUCCESS        0
                            // --------------------------------------------------------------------------
                            const TCHAR* pSource[] =
                            {
                             _T("1.bmp"),
                             _T("2.bmp"),
                             _T("3.bmp"),
                             _T("4.bmp"),
                             _T("5.bmp"),
                             _T("6.bmp"),
                             _T("7.bmp"),
                             _T("8.bmp"),
                             _T("9.bmp"),
                             _T("10.bmp"),
                             NULL
                            };
                            const TCHAR* pTarget[] =
                            {
                             _T("d:\\tmp\\20190505\\1.bmp"),
                             _T("d:\\tmp\\20190505\\2.bmp"),
                             _T("d:\\tmp\\20190505\\3.bmp"),
                             _T("d:\\tmp\\20190505\\4.bmp"),
                             _T("d:\\tmp\\20190505\\5.bmp"),
                             _T("d:\\tmp\\20190505\\6.bmp"),
                             _T("d:\\tmp\\20190505\\7.bmp"),
                             _T("d:\\tmp\\20190505\\8.bmp"),
                             _T("d:\\tmp\\20190505\\9.bmp"),
                             _T("d:\\tmp\\20190505\\10.bmp"),
                             NULL
                            };
                             
                            void* CopyMyFile(void *arg);
                             
                             
                            typedef struct
                            {
                             const TCHAR* pSource;
                             const TCHAR* pTarget;
                            } Files;
                             
                            static const int THREADS = 4;
                            // --------------------------------------------------------------------------
                            int main(void)
                            {
                             int status=0;
                             int status_addr=0;
                             
                             int iSource=0;
                             for(;;)
                             {    
                              Files fdata      [THREADS];
                              pthread_t thread [THREADS];
                              
                              for(int j=0;j<THREADS;++j) { thread[j].p=NULL; }      
                             
                              _tprintf(_T("iSource = %d\n"), iSource);
                              
                              for(int j=0;j<THREADS;++j,++iSource)
                              {    
                               if(pSource[iSource]==NULL) break;
                               fdata[j].pSource = pSource[iSource];
                               fdata[j].pTarget = pTarget[iSource];
                               status = pthread_create(&thread[j], NULL, CopyMyFile, (void *)&fdata[j]);
                               if(status != SUCCESS)
                               {
                                _tprintf(_T("pthread_create error, status = %d\n"), status);
                                break;
                               }      
                              }
                              int iExit=1;
                              for(int j=0;j<THREADS;++j)
                              {  
                               if(thread[j].p==NULL) continue;
                               iExit=0;
                               status = pthread_join(thread[j], (void**)&status_addr);
                               if (status != SUCCESS)
                               {
                                _tprintf("pthread_join error, status = %d\n", status);
                                break;
                               }
                              }
                              _tprintf(_T("iExit = %d\n"), iExit);
                              if(iExit) break;
                             
                             }
                             
                             
                            _tsystem(_T("pause"));
                             return 0;
                            }
                            // --------------------------------------------------------------------------
                            void* CopyMyFile(void *args)
                            {
                              _tprintf(_T("CopyFile: %s to %s\n"), ((Files*) args)->pSource, ((Files*) args)->pTarget);
                              
                              FILE *in  = fopen(((Files*) args)->pSource,"rb");
                              FILE *out = fopen(((Files*) args)->pTarget,"wb");
                             
                              if(in  == NULL) {  _tprintf(_T("in  == NULL\n")); return NULL;}
                              if(out == NULL) {  _tprintf(_T("out == NULL\n")); return NULL;}
                             
                              static const UINT SIZE=16384;
                              BYTE buffer[SIZE];
                              
                              for(;;)
                              {
                               DWORD Len = fread(buffer, 1, SIZE, in);  if(Len==0) break;
                               fwrite(buffer, 1, Len, out);
                              }
                              fclose(in);
                              fclose(out);
                             
                             return SUCCESS;
                            }
                            // --------------------------------------------------------------------------


                          Ошибки и ляпы тут могут быть, очень детально не проверял.
                          я в таком стиле вообще не работаю.
                            Цитата ЫукпШ @
                            я попробовал сделать то, что и ты, и у меня всё получилось.

                            Спасибо за участие.
                            Ахах if(Len==0) break; Как я не догадался...?
                            Добавил это в свой код,зацикливание исчезло,но появилась другая проблема.
                            Вылетает ошибка,если найденный файл превышает указанное ограничение размера.
                            Файл частично копируется(пару циклов) и вылетает ошибка.
                            Добавил проверку на существование создаваемого файла,на случай дублей.
                            Не помогло.
                            Сейчас функция выглядит так:
                            ExpandedWrap disabled
                              void * CopyMyFile(void * ffile)
                              {
                                  char file[MAX_PATH] = { 0 };
                                  strcpy(file, (CONST char *)ffile);
                                  free(ffile);
                               
                                  char new_file[MAX_PATH] = { 0 };
                                  strcpy(new_file, DriveS);
                                  strcat(new_file, NameFile);
                               
                                  find_file++;
                               
                                  FILE *ch = fopen(new_file,"rb");
                                  if (ch != NULL)
                                  {
                                      fclose(ch);
                                      pthread_mutex_unlock(&lock);
                                      return NULL;
                                  }
                               
                                  printf("%s\r\n", NameFile);
                               
                                  pthread_mutex_unlock(&lock);
                               
                                  FILE *in = fopen(file,"rb"), *out = fopen(new_file,"wb");
                                  if (in == NULL || out == NULL) {
                                     perror (file);
                                     return NULL;
                                  }
                                  rewind(out);
                               
                                  unsigned long int buf = 0;
                                  unsigned long int file_size = fsize(file);
                               
                                  if(file_size < 16384000)
                                      buf = (file_size + 64);
                                  else
                                      buf = 16384000;
                               
                                  BYTE *buffer = 0;
                                  if ((buffer = (BYTE *)malloc(buf *sizeof(BYTE)))==NULL)
                                  {
                                      printf("Buffer %s\r\n", strerror(errno));
                                      fclose(in);
                                      fclose(out);
                                      return NULL;
                                  }
                               
                                  while(!feof(in)) //тут возникает бесконечный цикл,при работе в более чем один поток
                                  {
                                      DWORD Len = fread(buffer, sizeof(BYTE), buf, in);
                                      
                                      if(Len==0) break;
                               
                                      fwrite(buffer, sizeof(BYTE), Len, out);
                                  }
                                  free(buffer);
                                  fclose(in);
                                  fclose(out);
                               
                                 return NULL;
                              }
                              Цитата Sherman @
                              Вылетает ошибка,если найденный файл превышает указанное ограничение размера.

                              В моей сборке это, как бы, не влияет.
                              Вот так тоже устойчиво работает:
                              Скрытый текст

                              ExpandedWrap disabled
                                void* CopyMyFile(void *args)
                                {
                                 _tprintf(_T("CopyFile: %s to %s\n"), ((Files*) args)->pSource, ((Files*) args)->pTarget);
                                  
                                 FILE *in  = _tfopen(((Files*) args)->pSource,_T("rb"));
                                 FILE *out = _tfopen(((Files*) args)->pTarget,_T("wb"));
                                 
                                 if(in  == NULL) { _tprintf(_T("in  == NULL\n")); return (void*)1;}
                                 if(out == NULL) { _tprintf(_T("out == NULL\n")); return (void*)2;}
                                 
                                // static const UINT SIZE=16384;
                                // BYTE buffer[SIZE];
                                 UINT SIZE = 16777216; // 16M
                                 BYTE* buffer=NULL;
                                 buffer = (BYTE*)malloc(SIZE);
                                 if(buffer==NULL) { _tprintf(_T("buffer == NULL\n")); return (void*)3; }      
                                  
                                // for(;;)
                                 while(!feof(in))
                                 {
                                  DWORD Len = fread(buffer, 1, SIZE, in);  
                                //  if(Len==0) { break; }
                                  fwrite(buffer, 1, Len, out);
                                 }
                                 fclose(in);
                                 fclose(out);
                                 free(buffer);
                                 
                                 return SUCCESS;
                                }


                              -----
                              Вот это попробуй для линкера:
                              -D_REENTRANT
                              У меня в проекте строка параметров линкера выглядит так:
                              -Wall -pipe -D_REENTRANT -s -lpthread
                                Цитата Sherman @
                                Я совсем не давно начал заниматься программированием и затрудняюсь вам ответить.
                                Вопрос был не в том, чтобы ты ответил, а в том, чтобы задумался, как должно было бы быть, и понял, почему стандартная библиотека должна знать о том, что она работает в многопоточном окружении и была реализована соответственно.
                                Цитата JoeUser @
                                Просьба к тебе, как к гуру Си и иже с ним... Разберись и проясни ситуацию. Тебе это обернется более "меньшей кровью" ввиду большего опыта.
                                Дык уже. Стандартная библиотека немногопоточная. Все признаки.

                                Добавлено
                                Цитата Sherman @
                                ExpandedWrap disabled
                                          if(Len==0) break;
                                В третий раз: почему не ferror()?
                                  Цитата Qraizer @
                                  В третий раз: почему не ferror()?

                                  Сделал так:
                                  ExpandedWrap disabled
                                        int err = 0;
                                        int err2 = 0;
                                        do
                                        {
                                            DWORD Len = fread(buffer, sizeof(BYTE), buf, in);
                                            
                                            fwrite(buffer, sizeof(BYTE), Len, out);
                                     
                                            err = ferror (in);
                                            err2 = ferror (out);
                                            if (err != 0)
                                                printf("R: %s\r\n", strerror(errno));
                                            if (err2 != 0)
                                                printf("W: %s\r\n", strerror(errno));
                                     
                                        }while(!feof(in));


                                  Выдаёт "W: Bad file descriptor"
                                    Цитата Qraizer @
                                    Добавлено
                                    Цитата Sherman @
                                    ExpandedWrap disabled
                                              if(Len==0) break;
                                    В третий раз: почему не ferror()?

                                    Это очень просто.
                                    Если файл завершился или произошла ошибка - выход из
                                    цикла чтения. Поскольку запись в этом случае бессмысленна.
                                    А вот потом можно производить тест на ошибки.


                                    Поэтому это неверно:
                                    Добавлено
                                    Цитата Sherman @
                                    Цитата Qraizer @
                                    В третий раз: почему не ferror()?

                                    Сделал так:
                                    ExpandedWrap disabled
                                          int err = 0;
                                          int err2 = 0;
                                          do
                                          {
                                              DWORD Len = fread(buffer, sizeof(BYTE), buf, in);
                                              
                                              fwrite(buffer, sizeof(BYTE), Len, out);
                                       
                                              err = ferror (in);
                                              err2 = ferror (out);
                                              if (err != 0)
                                                  printf("R: %s\r\n", strerror(errno));
                                              if (err2 != 0)
                                                  printf("W: %s\r\n", strerror(errno));
                                       
                                          }while(!feof(in));


                                    Выдаёт "W: Bad file descriptor"


                                    Если Len равно 0 всё равно надо выходить из цикла.
                                    И потом разбираться с ошибками.
                                    Сообщение отредактировано: ЫукпШ -
                                      Как можно реализовать похожую процедуру копирования файла на WIN API?
                                        Цитата Sherman @
                                        Как можно реализовать похожую процедуру копирования файла на WIN API?
                                        А зачем? Очередной раз говорю: проверь, что ты используешь многопоточную стандартную библиотеку. Тот факт, что код работает (хотя и написан не без изъянов) у всех, кроме тебя, ни на что не намекает? Совершенно неважно, каков у тебя движок потоков, хоть Плюсовый, хоть никсовый, хоть виндовый; если ты во многопоточном окружении используешь однопоточную CRT, она будет глючить, бажить и падать. Выхода два: первый уже озвучен, второй – вообще отказаться от любых стандартных функций языка.
                                        Сообщение отредактировано: Qraizer -
                                          Цитата Qraizer @
                                          Очередной раз говорю: проверь, что ты используешь многопоточную стандартную библиотеку.

                                          Да,но как это проверить?
                                            Цитата Sherman @
                                            Да,но как это проверить?
                                            Вот с этим не помогу. Нужен спец по МинГВе.
                                              Цитата Qraizer @
                                              Вот с этим не помогу. Нужен спец по МинГВе.

                                              Понял.В любом случае,спасибо за помощь.
                                                Цитата Sherman @
                                                Цитата Qraizer @
                                                Очередной раз говорю: проверь, что ты используешь многопоточную стандартную библиотеку.

                                                Да,но как это проверить?

                                                Так вот же:
                                                командная строка
                                                Используем поисковую систему, например www.ya.ru, пишем в строку "-D_REENTRANT".
                                                Смотрим, что получится.
                                                Сообщение отредактировано: ЫукпШ -
                                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                0 пользователей:


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