Код предположительно обрабатывает файл, открывает его, читает данные, что-то с ними делает, затем сохраняет результат в другой файл.
var
Stream: TFileStream;
begin
Stream := nil;
try
// что-то делаем
Stream := TFileStream.Create({ ... });
// что-то делаем
finally
Stream.Free;
end;
try
try
Stream := TFileStream.Create({ ... });
except
Exit;
end;
// что-то делаем
finally
Stream.Free;
end;
end;
Ответ.
Может произойти повторный Free на уже освобожденной переменной.
ОтветитьУдалитьСледует использовать FreeAndNil(Stream);
ну какая то совсем простая задачка :)
ОтветитьУдалитьКонечно AV будет.
в первом
Stream.Free;
Экземпляр класса освободился, а ссылка (переменная Stream) не обнулена
Далее в TFileStream.Create происходит exception,
except его гасит. Далее Exit и бодро идем... в последний finally
где Stream.Free; и AV :)
Создание экземпляров стримов применять ДО try верхней вложенности
ОтветитьУдалитьДа, видимо, если в первом "что-то делаем" что-то пойдет не так, то Create не выполнится, а перескочет сразу на Free.
ОтветитьУдалить1) Если в конструкторе произойдет исключение, то неявно вызовется деструктор.
ОтветитьУдалитьfinally выполнится всегда, а там уже битый указатель Stream
2) После Exit также произойдут вызовы всех finally, а там тот-же битый Stream
"После Exit также произойдут вызовы всех finally"
УдалитьА вот этого я не знал :o
Первый блок просто уродливый, но работоспособный.
ОтветитьУдалить2 Sibedir: первый "что-то делаем" поднимет исключение, управление перейдет к процедуре Free, которая защищена от таких ситуаций и не станет в этом случае звать деструктор.
Второй блок тоже уродливый, но не всегда работоспособен, а именно - если в первом блоке не было вовсе исключений, а во втором они случились в строке конструкции, то финализация во втором блоке вызовет второй раз деструктор одного и того же экземпляра, в котором будет обращение к полю [EAX]TFileStream.FHandle, что может привести к AV.
Да, спасибо. Действительно я не учел, что там nil, а [nil].Free не выполнится.
Удалить"[nil].Free" выполнится.
УдалитьВсмысле рейзить не будет.
Для того Free и создан вместо Destroy.
Я так понял, что нужно повнимательнее разобраться со стеком вызовов при обработке исключений?
ОтветитьУдалитьВроде, конкретных ошибок нет. Но create'ы внутри try..finally - потенциально опасно и криво.
ОтветитьУдалить