Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

После закрытия Ошибка Invalid Pointer Operation   Найти похожие ветки 

 
evgeso ©   (2011-02-25 15:31) [0]

Доброго времени суток.
При разработке приложения возник ошибка.
Ошибка возникает при закрытии формы приложения.
Вот код простого примера ошибки :

program Project1;

uses
 Forms,
 Unit1 in "Unit1.pas" {Form1},
 Unit2 in "Unit2.pas",
 Unit3 in "Unit3.pas";

{$R *.res}

begin
 Application.Initialize;
 Application.MainFormOnTaskbar := True;
 Application.CreateForm(TForm1, Form1);
 MyTest.Init;
 Application.Run;
end.

Unit1:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs,Unit3;

type
 TForm1 = class(TForm)
 private
   { Private declarations }
   FOwner    : IMyTest;
 public
   { Public declarations }
  procedure SetInterface(Value:IInterface);
  destructor Destroy;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

destructor TForm1.Destroy;
begin
 FOwner:=nil
end;

procedure TForm1.SetInterface(Value: IInterface);
begin
 FOwner:=IMyTEst(Value);
end;

end.

Unit2:
unit Unit2;

interface
 Uses Unit3,Unit1;
 type
   TMytest = class(TInterfacedObject,IMYTest)
      private
       function GetSelfInterface:IMyTest;
      public
       procedure Init;
   end;
 var
   MyTest:TMyTest;
implementation

{ TMytest }

function TMytest.GetSelfInterface: IMyTest;
begin
 Self.GetInterface(IMyTest,Result)
end;

procedure TMytest.Init;
begin
 Form1.SetInterface(GetSelfInterface);
end;

initialization
 MyTest:=TMyTest.Create;
finalization
 MyTest.Destroy

end.


unit Unit3;

interface
type
   IMyTest = interface
     ["{5432864A-87FE-40EB-A1F2-F10B68F33DAC}"]

   end;
implementation

end.

Как я понял ошибка возникает при вызове метода TObject.FreeInstance. А именно функция _FreeMem(Self);
Почему и как побороть у меня знаний не хватает.
Помогите уже с ума схожу.Полный дэбаг мод  :)


 
_Юрий   (2011-02-25 15:49) [1]

destructor Destroy; override;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

destructor TForm1.Destroy;
begin
FOwner:=nil;
 inherited;
end;


 
evgeso ©   (2011-02-25 16:03) [2]

Делал так
Ошибка всё равно возникает


 
Dimka Maslov ©   (2011-02-25 16:05) [3]

Для потомков TInterfacedObject нельзя явно вызывать деструктор. Это происходит автоматически при обнулении кол-ва ссылок.


 
evgeso ©   (2011-02-25 16:06) [4]

PS
Изначально пробовал так

procedure TMytest.Init;
begin
Form1.SetInterface(Self);
end;


 
_Юрий   (2011-02-25 16:10) [5]


> finalization
>  MyTest.Destroy
>


Не надо смешивать интерфейсную и объектную модель.
Объект будет разрушен автоматически по потере всех  ссылок (см. реализацию _Release в TInterfacedObject), вручную разрушать его не надо.

Правильнее так:

var
  MyTest:IMyTest;

finalization
MyTest:=nil


 
evgeso ©   (2011-02-25 16:14) [6]


> Для потомков TInterfacedObject нельзя явно вызывать деструктор.
>  Это происходит автоматически при обнулении кол-ва ссылок.
>


Согласен.
Я в курсе что метод
[CODE]
function TInterfacedObject._Release: Integer;
begin
 Result := InterlockedDecrement(FRefCount);
 if Result = 0 then
   Destroy;
end;
[/CODE]
уничтожает объект.
Тогда должна работать следующая конструкция
[CODE]
if Assigned(Engine) then
 Engine.Destroy;
[/CODE]
Но происходит та же ошибка.
Вопрос тогда TMyTest контролировать что объект будет уничтожен и все ресурсы созданные в нем тоже ?


 
evgeso ©   (2011-02-25 16:16) [7]

Ой с тегами ошибся сорри :)


 
Dimka Maslov ©   (2011-02-25 16:21) [8]

Внимательно надо читать про реализацию интерфейсов. Особенно для Delphi. Дело в том, что подсчёт количества ссылок ведётся неявно. При создании новой переменной указателя на интерфейс неявно вызывается метод AddRef, а при уничтожении переменной Release. При этом в Release при обнулении количества ссылок вызвается деструктор. Если мы не хотим, что бы это происходило и самостоятельно уничтожать объект, не надо наследовать его от класса TInterfacedObject, а унаследовав от TObject и IUnknown самостоятельно прописать действие методов QueryInterface, AddRef и Release.


 
Сергей М. ©   (2011-02-25 16:23) [9]


> finalization
>  MyTest.Destroy <--- грабли здесь



> procedure TMytest.Init;
> begin
>  Form1.SetInterface(GetSelfInterface);
> end;


Что твой интерфейсный объект делает в форме, о которой он знать ничего не должен ?


 
evgeso ©   (2011-02-25 16:44) [10]


> Что твой интерфейсный объект делает в форме, о которой он
> знать ничего не должен ?


Это простой пример. Он был сделан на скорую руку чтоб задать вопрос.
Просто основной проект смысла не было выкладывать.


> Внимательно надо читать про реализацию интерфейсов. Особенно
> для Delphi. Дело в том, что подсчёт количества ссылок ведётся
> неявно. При создании новой переменной указателя на интерфейс
> неявно вызывается метод AddRef, а при уничтожении переменной
> Release. При этом в Release при обнулении количества ссылок
> вызвается деструктор. Если мы не хотим, что бы это происходило
> и самостоятельно уничтожать объект, не надо наследовать
> его от класса TInterfacedObject, а унаследовав от TObject
> и IUnknown самостоятельно прописать действие методов QueryInterface,
>  AddRef и Release.


Я внимательно прочитал реализацию интерфейса.(TInterfacedObject =class(TInterfacedObject,IInterface))
И сказанное вами неоднократно встречал в книгах и статьях
Только совсем не думал что проверка типа

finalization
if Assigned(Engine) then // По идее здесь объект уже должен был быть разрушен
 Engine.Destroy;

Я переопределял методы AddRef,Release,BeforeDestruction.
С выводом отладочной информации о количестве ссылок и о стадиях разрушения объекта.
Но повторное разрушение объекта думал что предыдущий листинг исключит.

Спасибо всем за помощь. Вопрос снят. Приложение отрабатывает закрытие корректно.


 
evgeso ©   (2011-02-25 16:45) [11]


> Я внимательно прочитал реализацию интерфейса.(TInterfacedObject
> =class(TInterfacedObject,IInterface))

Очепятка

TInterfacedObject  =class (TObject,IInterface)


 
Dimka Maslov ©   (2011-02-25 16:53) [12]

Если объект разрушен, то откуда объект-владелец переменной Engine (непонятно окуда она вдруг взялась в обсуждении) будет знать о том, что объект разрушен? В переменной Engine не будет нуля, а будет адрес несуществующего уже объекта, повторное разрушение которого и вызвовет ошибку.


 
evgeso ©   (2011-02-25 17:06) [13]


> Dimka Maslov ©   (25.02.11 16:53) [12]
> Если объект разрушен, то откуда объект-владелец переменной
> Engine (непонятно окуда она вдруг взялась в обсуждении)
> будет знать о том, что объект разрушен? В переменной Engine
> не будет нуля, а будет адрес несуществующего уже объекта,
>  повторное разрушение которого и вызвовет ошибку.

Да, Engine,  это мой промах. Наверное нужно выйти подышать воздухом.:)
Получилось как в школе мне говорили смотришь в книгу,а видишь фигу
Вместо Engine имелось в виду TMyTest
> Dimka Maslov
Спасибо и извините. Потерял последовательность.
Тема закрыта



Страницы: 1 вся ветка

Текущий архив: 2013.03.22;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.166 c
2-1335292096
artemchik
2012-04-24 22:28
2013.03.22
настройка Delphi


1-1295711313
Gu
2011-01-22 18:48
2013.03.22
Диалог "Свойства файла" для нескольких файлов папок


15-1335461156
alexdn
2012-04-26 21:25
2013.03.22
pdf программка


2-1331794898
bash77
2012-03-15 11:01
2013.03.22
очистить массив, удалить или еще чего с ним


3-1284795538
vhm
2010-09-18 11:38
2013.03.22
Подключение к MySQL