Эта программа, "16 Summation.exe" (см. листинг на рис. 16-6), демонстрирует исполь зование фильтров и обработчиков исключений для корректного восстановления пос ле переполнения стека. Файлы исходного кода и ресурсов этой программы находят ся в каталоге l6-Summation на компакт-диске, прилагаемом к книге. Возможно, Вам придется сначала прочесть главы по SEH, чтобы понять, как работает эта программа. Она суммирует числа от 0 до x, где x — число, введенное пользователем. Конечно, проще было бы написать функцию с именем Sum, которая вычисляла бы по формуле:
Sum = (x * (x + 1)) / 2;
Но для этого примера я сделал функцию Sum рекурсивной, чтобы она использо вала большое стековое пространство.
При запуске программы появляется диалоговое окно, показанное ниже.
В этом окне Вы вводите число и щелкаете кнопку Calculate. Программа создает поток, единственная обязанность которого - сложить все числа от 0 до x. Пока он выполняется, первичный поток программы, вызвав WaitForSingleOhject, просит систе му не выделять ему процессорное время. Когда новый поток завершается, система вновь выделяет процессорное время первичному потоку. Тот выясняет сумму, полу чая код завершения нового потока вызовом GetExitCodeThread, и — это очень важно — закрывает свой описатель нового потока, так что система может уничтожить объект ядра "поток", и утечки ресурсов не произойдет.
Далее первичный поток проверяет код завершения суммирующего потока. Если он равен UINT_MAX, значит, произошла ошибка: суммирующий поток переполнил стек при подсчете суммы; тогда первичный поток выведет окно с соответствующим сообщением. Если же код завершения отличен от UINT_MAX, суммирующий поток
отработал успешно; код завершения и есть искомая сумма. Б этом случае первичный поток просто отображает результат суммирования в диалоговом окне.
Теперь обратимся к суммирующему потоку, Его функция — SumThreadFunc, При создании этого потока первичный поток передает ему в единственном параметре pvParam количество целых чисел, которые следует просуммировать. Затем его функ ция инициализирует переменную uSum значением UINT_MAX, т. e. изначально пред полагается, что работа функции не завершится успехом Далсс SumThreadFunc акти визирует SEH так, чтобы перехватывать любое исключение, возникающее при вы полнении потока. После чего для вычисления суммы вызывается рекурсивная функ ция Sum.