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


Некоторые соображения по библиотеке С/С++ - часть 7


Этот момент, кстати, очень важен. Если бы Вы создали поток с помощью CreateThread, а потом вызвали библиотечную функцию signal, она работала бы некорректно.
  • Далее вызывается функция потока, которой передается нужный параметр. Адрес этой функции и ее параметр были сохранены в блоке tiddata функцией _beginthreadex.
  • Значение, возвращаемое функцией потока, считается кодом завершения этого потока. Обратите внимание: _threadstartex не возвращается в BaseThreadStart. Иначе после уничтожения потока его блок tiddata так и остался бы в памяти. А это привело бы к утечке памяти в Вашем приложении. Чтобы избежать этого, threadstartex вызывает другую библиотечную функцию, _endthreadex, и передает ей код завершения.
  • Последняя функция, которую нам нужно рассмотреть, — это _endthreadex (ее исходный код тоже содержится в файле Threadex.c). Вот как она выглядит в моей версии (в псевдокоде).

    void _cdecl _endthreadex (unsigned retcode)
    {
    _ptiddata ptd;
    // указатель на блок данных потока

    // здесь проводится очистка ресурсов, выделенных для поддержки операций
    // над числами с плавающей точкой (код не показан)

    // определение адреса блока tiddata данного потока
    ptd = _getptd();

    // высвобождение блока tiddata
    _freeptd(ptd);

    // завершение потока
    ExitThread(retcode);
    }

    Несколько важных моментов, связанных с _endthreadex.

    • Библиотечная функция _getptd обращается к Windows-функции TlsGetValue, которая сообщает адрес блока памяти tiddata вызывающего потока.
    • Этот блок освобождается, и вызовом ExttThread поток разрушается. При этом, конечно, передается корректный код завершения.

    Где-то в начале главы я уже говорил, что прямого обращения к функции ExitThread следует иpбегать. Это правда, и я не отказываюсь от своих слов. Тогда же я сказал, что это приводит к уничтожению вызывающего потока и не позволяет ему вернуться из выполняемой в данный момент функции. А поскольку она не возвращает управление, любые созданные Вами С++-объекты не разрушаются. Так вот, теперь у Вас есть еще одна причина не вызывать ExitThread, она не дает освободить блок памяти tiddata потока, из-за чего в Вашем приложении может наблюдаться утечка памяти (до его pавершения).




    Начало  Назад  Вперед