| 
| 
 | Вопрос # 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™: ну так вот этим же и не устраивает, я же сразу написал, что это практически невыполнимо...
 |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |