Форум: "Основная";
Текущий архив: 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.077 c