Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

После закрытия Ошибка 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.071 c
15-1353223486
AV
2012-11-18 11:24
2013.03.22
Как правильно сказать по- английски


2-1340983618
AntonMos
2012-06-29 19:26
2013.03.22
фильтр DBGRIDEH


2-1342447542
Sergio_Leone
2012-07-16 18:05
2013.03.22
Как определить запуск 3D приложения?


2-1345804953
Wadimka
2012-08-24 14:42
2013.03.22
Подскажите можно ли с консольным приложением..


2-1336632149
igorium
2012-05-10 10:42
2013.03.22
Чтение названий файлов в написанных НЕрусскими и НЕанглийскими





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский