|
Вопрос # 6 501/ вопрос открыт / |
|
Приветствую, уважаемые эксперты!
Вопрос таков: как отличить, в каком случае лучше использовать FreeAndNil, а в каком просто Free?
var
tc: TRttiContext;
begin
tc := TRttiContext.Create;
FreeAndNil(tc);
end;
Вот так на выдаёт Access violation. То есть нужно пользоваться tc.Free. Вопрос в том, как заранее узнать, можно ли использовать FreeAndNil, до выполнения? При том, чтобы не лазить каждый раз в исходники того или иного класса с целью узнать, подходит ли он для FreeAndNil
Примечание #1 (13 декабря 2013, 16:36): блин... накосячил с тегами... а редактровать нельзя(
 |
Вопрос задал: dmistand (статус: 1-ый класс)
Вопрос отправлен: 13 декабря 2013, 16:35
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: min@y™
Не буду говорить "как надо", просто скажу, как делаю я. А я использую FreeAndNil() для глобальных объектов (особенно, когда потом надо проверять существование if Assigned(...) then...), а Free() - для локальных. Не буду спорить на тему "правильно это или нет", просто всё работает и хрен бы с ним.
По поводу приведённого куска кода:
var
tc: TSomeClass;
begin
tc:= TSomeClass.Create(...);
try
// работа с экземпляром класса
finally
tc.Free();
end;
end;
Я кончел и закурил... :)
 |
Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 14 декабря 2013, 13:46
Оценка за ответ: 5
|
Мини-форум вопроса
Всего сообщений: 8; последнее сообщение — 14 декабря 2013, 22:31; участников в обсуждении: 3.
|
min@y™ (статус: Доктор наук), 14 декабря 2013, 13:48 [#1]:
Цитата (dmistand):
блин... накосячил с тегами... а редактровать нельзя(
Тебе нельзя, а мне можно!
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
dmistand (статус: 1-ый класс), 14 декабря 2013, 14:12 [#2]:
min@y™: а как узнать что для объекта допустимо использование FreeAndNil? А то бывает, вроде объект, вроде подходит. А выдаёт Access violation. Как в примере.
|
|
min@y™ (статус: Доктор наук), 14 декабря 2013, 14:40 [#3]:
Цитата (dmistand):
а как узнать что для объекта допустимо использование FreeAndNil? А то бывает, вроде объект, вроде подходит. А выдаёт Access violation. Как в примере.
Элементарно! Если вылезает AV, тогда не подходит! И всего делов!
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
min@y™ (статус: Доктор наук), 14 декабря 2013, 14:46 [#4]:
Да, и ещё... Вот пример использования FreeAndNil(), выдранный из моего проекта:
unit uGotoLineForm;
interface
uses
//============================== Модули проекта ==============================
uTypes, uPages, uRoutines, uSettings,
//=============================== Левые модули ===============================
Placemnt,
//=================== Системные модули и модули компонентов ==================
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TGotoLineForm = class(TForm)
Label1: TLabel;
LineComboBox: TComboBox;
GoButton: TButton;
CloseButton: TButton;
FormStorage: TFormStorage;
procedure LineComboBoxKeyPress(Sender: TObject; var Key: Char);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure GoButtonClick(Sender: TObject);
private
{ Private declarations }
public
FPage: TSynEditPage;
constructor Create(AOwner: TComponent); override;
function ShowModal: Integer; override;
end;
var
GotoLineForm: TGotoLineForm;
procedure GotoLine(APage: TSynEditPage);
implementation
{$R *.dfm}
procedure GotoLine(APage: TSynEditPage);
begin
if not Assigned(GotoLineForm)
then GotoLineForm:= TGotoLineForm.Create(Application);
try
GotoLineForm.FPage:= APage;
GotoLineForm.ShowModal();
finally
FreeAndNil(GotoLineForm);
end;
end;
constructor TGotoLineForm.Create(AOwner: TComponent);
begin
inherited;
// Инициализация
FormStorage.IniSection:= 'Forms\' + Name;
end;
procedure TGotoLineForm.LineComboBoxKeyPress(Sender: TObject;
var Key: Char);
begin
if not (Key in ['0'..'9', #8])
then Key:= #0;
end;
procedure TGotoLineForm.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13
then GoButton.Click();
end;
procedure TGotoLineForm.GoButtonClick(Sender: TObject);
var
ALine: Integer;
begin
if TryStrToInt(LineComboBox.Text, ALine)
then begin
FPage.SynEdit.GotoLineAndCenter(ALine);
PushStringItem(GotoLineForm.LineComboBox.Items, GotoLineForm.LineComboBox.Text);
ModalResult:= mrOk;
end;
end;
function TGotoLineForm.ShowModal: Integer;
begin
// Загрузка в комбобокс строк, введённых ранее
LineComboBox.Items.Assign(TStringListOption(ProgramSettings.OptionsByName[snGotoLines]).List);
Result:= inherited ShowModal();
// Сохранение строк, введённых ранее
TStringListOption(ProgramSettings.OptionsByName[snGotoLines]).List.Assign(LineComboBox.Items);
end;
end.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
DNK (статус: Студент), 14 декабря 2013, 14:53 [#5]:
Не сталкивался с TRttiContext ни разу - не знаю что это такое. У меня есть одна теория. Что мы имеем:
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
FreeAndNil сначала копирует указатель в свою локальноую переменную, обнуляет указанную переменную и только потом вызывает метод Free.
Если указанный класс образован от TInterfacedObject, то строка Pointer(Obj) := nil; может привести к неявному вызову метода:
function TInterfacedObject._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
При условии если на указанный объект больше не останется ссылок (в случае локальной переменной это именно так), это автоматически приводит к уничтожению объекта.
Поэтому явный вызов деструкора в следующей строке и не может уничтожить уже уничтоженный объект.
"Digital Networked Knight"
|
|
dmistand (статус: 1-ый класс), 14 декабря 2013, 18:22 [#6]:
min@y™: а на этапе компиляции? AV только во время выполнения же... А не всегда удаётся прогнать и проверить всё. Кстати, подсмотрел у вас разделение в uses части, спасибо )
DNK: мысль интересная и, скорее всего, верная, спасибо.
|
|
min@y™ (статус: Доктор наук), 14 декабря 2013, 18:36 [#7]:
Цитата (dmistand):
а на этапе компиляции? AV только во время выполнения же...
А никак. Чем тебя не устраивает запустить прогу и проверить, как она работает? Это ж и есть отладка, чортвозьми!
Цитата (dmistand):
А не всегда удаётся прогнать и проверить всё.
Это очень плохо. Это ОЧЕНЬ плохо! Сочувствую, по себе знаю. Печальная шняга.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
dmistand (статус: 1-ый класс), 14 декабря 2013, 22:31 [#8]:
> Чем тебя не устраивает запустить прогу и проверить, как она работает?
> Цитата (dmistand):
> А не всегда удаётся прогнать и проверить всё.
> Это очень плохо. Это ОЧЕНЬ плохо! Сочувствую, по себе знаю. Печальная шняга.
min@y™: ну так вот этим же и не устраивает, я же сразу написал, что это практически невыполнимо...
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|