Windows для профессионалов

       

Библиотечные функции, которые лучше не вызывать


В библиотеке С/С++ содержится две функции:

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.



Содержание раздела