Библиотечные функции, которые лучше не вызывать
В библиотеке С/С++ содержится две функции:
unsigned long _beginthread( void (__cdecl *stait_address)(void *), unsigned stack_size, void *arglist);
и
void _endthread(void);
Первоначально они были созданы для того, чем теперь занимаются новые функ ции _beginthreadex и _endthreadex. Нo, как видите, у _begintbread параметров меньше, и, следовательно, ее возможности ограничены в сравнении с полнофункциональной beginthreadex. Например, работая с _beginthread, нельзя создать поток с атрибутами защиты, отличными от присваиваемых по умолчанию, нельзя создать поток и тут же его задержать — нельзя даже получить идентификатор потока. С функцией _endthread та же история; она не принимает никаких параметров, а это значит, что по оконча нии работы потока его код завершения всегда равен 0.
Однако с функцией _endthread дело обстоит куда хуже, чем кажется: перед вызо вом ExitThread она обращается к CloseHandle и передает ей описатель нового потока. Чтобы разобраться, в чем тут проблема, взгляните на следующий код:
DWORD dwExitCode;
HANDLE hThreatf = _beglntnread(...);
GetExitCodeThread(hThread &dwExitCode);
CloseHandle(hThread);
Весьма вероятно, что созданный поток отработает и завершится еще до того, как первый поток успеет вызвать функцию GetExitCodeThread. Если так и случится, значе ние в hThread окажется недействительным, потому что _endtbread уже закрыла опи сатель нового потока. И, естественно, вызов CloseHandle дает ошибку.
Новая функция _endthreadex, не закрывает описатель потока, поэтому фрагмент кода, приведенный выше, будет нормально работать (если мы, конечно, заменим вы зов _beginthread на вызов _beginthreadex) И в заключение, напомню еще раз: как толь ко функция потока возвращает управление, _beginthreadex самостоятельно вызывает _endthreadex, a begtnthreadобращается к_endthread.