Windows

       

Функция ExitProcess


Процесс завершается, когда один из его потоков вызывает ExitProcess:

VOID ExilProcess(UINT fuExitCode);

Эта функция завершает процесс и заносит в параметр fuExitCode код завершения процесса. Возвращаемого значения у ExitProcess нет, так как результат ее действия — завершение процесса. Если за вызовом этой функции в программе присутствует ка кой-нибудь код, он никогда не исполняется.

Когда входная функция (WinMain, wWinMain, main или wmairi) в Вашей програм ме возвращает управление, оно передастся стартовому коду из библиотеки С/C++, и тот проводит очистку всех ресурсов, выделенных им процессу, а затем обращается к

ExitProcess, передавая ей значение, возвращенное входной функцией Вот почему воз врат управления входной функцией первичного потока приводит к завершению все го процесса. Обратите внимание, что при завершении процесса прекращается выпол нение и всех других его потоков.

Кстати, в документации из Platform SDK утверждается, что процесс не завершает ся до тех пор, пока не завершится выполнение всех его потоков. Это, конечно, верно, но тут есть одна тонкость. Стартовый код ил библиотеки С/С++ обеспечивает завер шение процесса, вызывая ExitProcess после того, как первичный поток Вашего прило жения возвращается из входной функции. Однако, вызвав из нее функцию ExitThread (вместо того чтобы вызвать ExitProcess или просто вернуть управление), Вы заверши те первичный поток, но не сам процесс — если в нем еще выполняется какой-то дру гой поток (или потоки).

Заметьте, что такой вызов ExitProcess или ExitTbread приводит к уничтожению процесса или потока, ко1да выполнение функции еще не завершилось. Что касается операционной системы, то здесь все в порядке: она корректно очистит все ресурсы, выделенные процессу или потоку Но в приложении, написанном на С/С++, следует избегать вызова этих функций, так как библиотеке С/С++ скорее всего нс удастся провести должную очистку. Взгляните на этот код:

#include <windows n>
#include <stdio h>

class CSomeObj {


public:
CSomeOtrK) { printf("Constructor\r\n"), }
~CSomeObj() { printf("Destructor\r\n"); }
};

CSomeObj g_GlobalObj;

void main () {
CSomeObj LocalObj;
ExitProcess(0); // этого здесь не должно быть

// в конце этой функции компилятор автоматически вставил код // дли вызова деструктора LocalObj, но ExitProcess не дает его выполнить }

При его выполнении Вы увидите:

Constructor
Constructor

Код конструирует два объекта: глобальный и локальный Но Вы никогда не увиди те строку Destructor С++-объекты не разрушаются должным образом из-за того, что ExitProcess форсирует уничтожение процесса и библиотека С/С++ не получает шанса на очистку.

Как я уже говорил, никогда не вызывайте ExitProcess в явном виде. Если я уберу из предыдущего примера вызов ExttProcess, программа выведет такие строки:

Constructor
Constructor

Destructor
Destructor

Простой возврат управления от входной функции первичного потока позволил библиотеке С/С++ провести нужную очистку и корректно разрушить С++-объекты. Кстати, все, о чем я рассказал, относится не только к объектам, но и ко многим дру гим вещам, которые библиотека С/С++ делает для Вашего процесса.

NOTE
Явные вызовы ExitProcess и ExitTbread — распространенная ошибка, которая мешает правильной очистке ресурсов. В случае ExitTbread процесс продолжа ет работать, но при этом весьма вероятна утечка памяти или других ресурсов.


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