AlexCasual
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 «  : 14-07-2011 20:30 »   | 
								
								 | 
							  
							 
							Имеется цикл в котором создаются потоки с одинаковой потоковой функцией find_in_path() :
  hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)find_in_path,NULL,0,NULL);
  Если я правильно понимаю,то все переменные,определённые внутри find_in_path(),будут локальными для каждого из создаваемых потоков и доступ к ним синхронизировать не нужно? - Но при таком ходе мысли у меня нарушается логика работы функции find_in_path() в каждом из потоков (попрасту говоря - неверно работает)...Если же код внутри find_in_path() обернуть в критическую секцию,то всё работает верно... Или я чего-то не понимаю?
  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Вад
							
						 | 
						
							
								  | 
								
									
									 « Ответ #1 : 14-07-2011 20:40 »   | 
								
								 | 
							  
							 
							Есть нюансы.  Во-первых, если есть статические переменные в функции find_in_path, то будет существовать только один экземпляр такой переменной (возможно, даже будет неопределённое поведение), поскольку такие переменные создаются в момент первого вызова функции. Во-вторых, использование функций из Runtime-библиотеки (CRT) может окончиться плохо в многопоточной среде, потому что они используют глобальные переменные. Чтобы таких проблем не было, нужно использовать  _beginthread/_beginthreadex вместо CreateThread.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Антон (LogRus)
							
						 | 
						
							
								  | 
								
									
									 « Ответ #2 : 15-07-2011 04:04 »   | 
								
								 | 
							  
							 
							Осмелюсь добавить, что не только статики могут сыграть дурную шутку, но и вообще любые внешние данные по отношению к функции которые могу менятся в паралельных потоках: - глобальные переменные - общий массив выходных данных - входная очередь запросов также стоит отметить, что проблема может скрыватся в самом используемом алгоритме, если он не учитывает многопоточный запуск
  Хотелось бы посмотреть на код find_in_path, не видя кода можно строить сколь угодно хитрые теории, которые никак не связаны с жизью 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							Странно всё это.... 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							AlexCasual
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #3 : 15-07-2011 16:27 »   | 
								
								 | 
							  
							 
							В функции find_in_path() я использую связку FindFirstFile()/FindNextFile() - может ли это быть причиной глюкавости работы? А хотя вот и код : bool find_in_path(const char *_path) {         WIN32_FIND_DATA ffd;         HANDLE hFind;
          std::string path = _path;         std::string thread_path = _path;
          path.append("\\*.*");
           printf("%s %s \n","THREAD***",path.c_str());          printf("%s %d \n","ID",GetCurrentThreadId());
          hFind = FindFirstFile(path.c_str(),&ffd);
          while(FindNextFile(hFind,&ffd) != 0)         {                                        if(strcmp(ffd.cFileName,"..") != 0)                 {                         if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)                     {                                         thread_path = path;                                         thread_path.resize(thread_path.size() - 3);                                         thread_path.append("\\");                                         thread_path.append(ffd.cFileName);
                                          //find_in_path(thread_path.c_str());                                         start_thread(thread_path.c_str());                                 }                                 else                                 {    printf("%s \n","FILE***");                                          printf("%s \n",ffd.cFileName);                                 }                                                               }                 }    FindClose(hFind);
          return true; }  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 15-07-2011 22:50 от RXL »
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Ochkarik
							
						 | 
						
							
								  | 
								
									
									 « Ответ #4 : 15-07-2011 22:07 »   | 
								
								 | 
							  
							 
							std::string  не очень потокобезопасна, насколько я слышал.... проверьте)
  PS start_thread(thread_path.c_str()); - это шо? 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 15-07-2011 22:21 от Ochkarik »
								 | 
								
									 
									Записан
								 | 
							  
							 
							RTFM уже хоть раз наконец!     :[ ну или хотя бы  STFW...  
						 | 
					 
				 
			 |  
		 
	 | 
	| 
		
		
	 | 
	
		
		
			
				
					
						| 
							Антон (LogRus)
							
						 | 
						
							
								  | 
								
									
									 « Ответ #6 : 16-07-2011 17:29 »   | 
								
								 | 
							  
							 
							std::string  не очень потокобезопасна, насколько я слышал.... проверьте)
  оно тут не причём, переменная локальная и не шарится потоками AlexCasual,          EnterCriticalSection(&cs); 	memcpy(str,_path,256);         LeaveCriticalSection(&cs);
  что такое str и и почему оно в критической секции? дай угадаю, глобальная переменная, которая вроде как защинена? но она ничем не защищена на самом, то деле ты её еще не успел передать в поток, а оно уже поменялось другим потоком memcpy в состоянии вызвать ошибку доступа к памяти, т.к. оно не проверяет размер входного буфера strncpy(str,_path,256); str[sizeof(str) - 1 ] = 0;  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							Странно всё это.... 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Ochkarik
							
						 | 
						
							
								  | 
								
									
									 « Ответ #7 : 16-07-2011 20:51 »   | 
								
								 | 
							  
							 
							Антон (LogRus), могло бы быть "при чем", я ж кода start_thread не видел куда буфер уплывает   просто такую фразу нашел... ...но поскольку специалистом по С++ не являюсь, интересно услышать ваше мнение Рассмотрим пример:
  std::string   a = "abc"; std::string b = a; Для многих реализаций обе переменные a и b будут указывать на один и тот же буфер в памяти, по-возможности, отслеживая моменты, когда необходимо "расщепить" общий буфер, дав каждой переменной по своей копии.
  Однако в случае многонитевых приложений подобная политика запросто приводит к возникновению т.н. raise condition, например, одна нить может уничтожить одну переменную, а другая - что-то записать в нее. При этом сущесвтует вероятность того, что произойдет обращение к уже освобожденному блоку памяти и падению программы. - стринги действительно могут ТАК выделять память? источник PS str[sizeof(str) - 1 ] = 0; - не только. ошибка еще и в том, что размер _path - может быть меньше 256. тогда выход за границы при копировании. в случае если размер больше... ошибка по отсутствию нуля в конце, либо выход за границы но уже в новой нити, при инициализации стрингов. PPS размер пути в NTFS может достигать 32к символов юникода, каждая компонента - до 256 символов.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 16-07-2011 21:08 от Ochkarik »
								 | 
								
									 
									Записан
								 | 
							  
							 
							RTFM уже хоть раз наконец!     :[ ну или хотя бы  STFW...  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Антон (LogRus)
							
						 | 
						
							
								  | 
								
									
									 « Ответ #8 : 18-07-2011 05:19 »   | 
								
								 | 
							  
							 
							Ochkarik, уг   что касается цитаты, то я не видел ни разу такой реализации (глядел на STLport, gcc и в STL от MS не припомню такого), а пукт "21.4.2   basic_string constructors and assigment operators" утвержадет, что конструктор создаёт копию. В любом случае я думаю писатели библиотек учли бы особенность нитей при реализации CopyOnWrite для строк, иначе имхо поведение слишком не детерминированно, что бы ей пользоваться про PS: поэтому там строчкой выше копирование через strncpy  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							Странно всё это.... 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Вад
							
						 | 
						
							
								  | 
								
									
									 « Ответ #9 : 18-07-2011 08:05 »   | 
								
								 | 
							  
							 
							Я бы, в любом случае, запускал поток через _beginthread/_beginthreadex - строка, может, и не при чём, но CRT там в хвост и в гриву используется - где-нибудь что-нибудь да всплывёт. Тот же printf наверняка использует какой-нибудь не-потокобезопасный буфер. 
  Кстати, от printf, вызываемого из многих потоков разом, я бы и не ожидал корректной работы. Если этот вывод нужен - лучше его как-то изолировать. 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Ochkarik
							
						 | 
						
							
								  | 
								
									
									«  Ответ #10 : 18-07-2011 10:24 »    | 
								
								 | 
							  
							 
							Антон (LogRus), да, пардон, слона то я и не заметил) 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							RTFM уже хоть раз наконец!     :[ ну или хотя бы  STFW...  
						 | 
					 
				 
			 |  
		 
	 | 
	 |