Код предположительно обрабатывает файл, открывает его, читает данные, что-то с ними делает, затем сохраняет результат в другой файл.
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 - потенциально опасно и криво.
ОтветитьУдалить