Ответ на задачку №24
Александр АлексеевОтвет на задачку №24.
Задачка была про «чистое» и «грязное» завершение работы программы. Иногда я вижу такую классификацию:
TerminateProcess
— самое «грязное» завершение работы процесса. Процесс и потоки убиваются сразу. Код очистки (финализация DLL) не выполняется.ExitProcess
— более «правильное» завершение процесса. Выполняется код очистки DLL.Halt
— аналогExitProcess
в RTL языка. Дополнительно выполняет очистку RTL (финализация модулей и др.).Application.Terminate
— заменаHalt
для приложений на VCL (с циклом выборки сообщений). Стоит немного отдельно, так как не выполняет немедленного завершения процесса. Зато позволяет провести более полную очистку (финализация форм и т.п.).
С этой точки зрения Halt
выглядит предпочтительнее ExitProcess
и уж тем более — TerminateProcess
. И если приложение не использует VCL, то может показаться, что это — даже и правильное завершение процесса.
Тем не менее, в указанном коде есть одна явная и одна потенциальная проблемы.
Начнём со слона в комнате: Halt
выполняет немедленное завершение программы — что означает, что никакой код после Halt
не выполняется. В том числе — и очистка строки S
. Это означает, что в этом коде — утечка памяти. Это и был вопрос задачки.
Да, это может не иметь значения на практике, поскольку вся память процесса будет освобождена ОС при выходе. Тем не менее, она будет определена как утечка любым отладочным инструментом для поиска утечек памяти. Иными словами, её нужно устранить.
Второй проблемы может и не быть в конкретно взятой программе (т.е. к задачке это отношения уже не имеет), но потенциально она возникнуть может (и легко). Надо иметь в виду, что Halt
не выполняет полную (читай: «правильную») очистку, поскольку любые вышестоящие блоки finally
не выполняются. Зато Halt
выполняет секции finalization
ваших модулей. С точки зрения программы у неё «волшебным» образом при выполнении оказываются пропущенными блоки кода. В частности, в пропущенных блоках может стоять финализация фоновых потоков. Т.е. при использовании Halt
фоновые потоки будут всё ещё выполняться — что может оказаться неожиданным для кода очистки из секций finalization
. Т.е. открываются широкие возможности для блокировок, ошибок доступа и т.п.
Мораль истории: не используйте Halt
и ExitProcess
. Если вам нужно чисто выйти из процесса, то нужно сделать это «естественным» способом — просто закончить выполнение главной процедуры основного потока. Чтобы перейти к её концу из произвольного места, можно использовать Exit
и/или Abort
(с подходящей конструкцией обработки на верхнем уровне).
А если вам нужно экстренно завершить процесс, то используйте TerminateProcess
.
В трёх экземплярах, будьте добры
Александр АлексеевЭто перевод Windows Confidential: In Triplicate, Please? Автор: Реймонд Чен.
Однажды клиент заметил, что размер файла, о котором сообщал Explorer, не меняется, пока приложение, которое обновляет
При отключении службы планировщика заданий происходят всякие плохие вещи. Это плохо или нет?
Александр АлексеевЭто перевод All sorts of bad things happen when we disable the Task Scheduler service, is that bad? Автор: Реймонд Чен.
Клиент при помощи групповой политики
Ранняя история файловых атрибутов Windows, и почему в них есть место между System и Directory
Александр АлексеевЭто перевод The early history of Windows file attributes, and why there is a gap between System and Directory. Автор: Реймонд Чен.
Если вы посмотрите на
Отчёт об уязвимости, раздвигающий границы криптографии
Александр АлексеевЭто перевод Pushing the boundaries of cryptography in a security vulnerability report. Автор: Реймонд Чен.
К нам поступил отчёт об уязвимости в безопасности, в котором сообщалось,
Деревообработка — противоположность разработке ПО
Александр АлексеевЭто перевод Woodworking, the opposite of software development. Автор: Реймонд Чен.
Ожидая автобус на остановке, я встретил бывшего разработчика программного обеспечения, который сказал, что теперь он
Задачка №24
Александр Алексеевprocedure DoSomething;
var
S: String;
begin
S := CalculateSomething;
ShowMessage(S);
Halt;
end;
Дело о случайных вылетах
Александр АлексеевОдин начинающий программист спросил, почему вылетает с Access Violation очень простой и, что интереснее, явно корректный код.
Примечание: слово «случайных» в заголовке означает, что вылет происходит в непредсказуемом месте — разном, в зависимости от приложения. Но в рамках одного конкретного приложения вылет всегда детерминирован (и, следовательно, воспроизводим).
Я не буду приводить код целиком, потому что, во-первых, он не имеет отношения к вопросу, во-вторых, он многократно менялся. Автор вопроса показал себя мастером скрывать данные и давать неточные показания.
Ответ на задачку №23
Александр АлексеевОтвет на задачку №23.
Довольно много людей обратили внимание на такую конструкцию:
try SomeVariable := TSomeClass.Create({...}); // ... finally SomeVariable.Free; end;
«Это неправильно, правильно — так:»