Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 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 Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: 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™

min@y™ (статус: Доктор наук), 14 декабря 2013, 13:48 [#1]:

Цитата (dmistand):

блин... накосячил с тегами... а редактровать нельзя(

Тебе нельзя, а мне можно! :)
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
dmistand

dmistand (статус: 1-ый класс), 14 декабря 2013, 14:12 [#2]:

min@y™: а как узнать что для объекта допустимо использование FreeAndNil? А то бывает, вроде объект, вроде подходит. А выдаёт Access violation. Как в примере.
min@y™

min@y™ (статус: Доктор наук), 14 декабря 2013, 14:40 [#3]:

Цитата (dmistand):

а как узнать что для объекта допустимо использование FreeAndNil? А то бывает, вроде объект, вроде подходит. А выдаёт Access violation. Как в примере.

Элементарно! Если вылезает AV, тогда не подходит! :-D И всего делов!
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
min@y™

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

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

dmistand (статус: 1-ый класс), 14 декабря 2013, 18:22 [#6]:

min@y™: а на этапе компиляции? AV только во время выполнения же... А не всегда удаётся прогнать и проверить всё. Кстати, подсмотрел у вас разделение в uses части, спасибо :))

DNK: мысль интересная и, скорее всего, верная, спасибо.
min@y™

min@y™ (статус: Доктор наук), 14 декабря 2013, 18:36 [#7]:

Цитата (dmistand):

а на этапе компиляции? AV только во время выполнения же...

А никак. Чем тебя не устраивает запустить прогу и проверить, как она работает? Это ж и есть отладка, чортвозьми!

Цитата (dmistand):

А не всегда удаётся прогнать и проверить всё.

Это очень плохо. Это ОЧЕНЬ плохо! Сочувствую, по себе знаю. Печальная шняга.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
dmistand

dmistand (статус: 1-ый класс), 14 декабря 2013, 22:31 [#8]:

> Чем тебя не устраивает запустить прогу и проверить, как она работает?
> Цитата (dmistand):
> А не всегда удаётся прогнать и проверить всё.
> Это очень плохо. Это ОЧЕНЬ плохо! Сочувствую, по себе знаю. Печальная шняга.

min@y™: ну так вот этим же и не устраивает, я же сразу написал, что это практически невыполнимо...

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 16:31
Выполнено за 0.03 сек.