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

Вниз

Ошибка после удаления интерфейса   Найти похожие ветки 

 
Семен Сорокин ©   (2005-05-18 17:36) [0]

Приветствую, пол дня бьюсь над одной проблемой:

имеется следующее описание:

unit Unit1;

interface

uses
 Classes;

type
 TNoRefrencedObject = class(TObject)
 protected
   function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
   function _AddRef: Integer; stdcall;
   function _Release: Integer; stdcall;
 end;

 TBaseListClass = class(TNoRefrencedObject, IUnknown)
 private
   FItems: TStrings;
 public
   constructor Create;
   destructor Destroy; override;
 end;

 IInterface1 = interface
 ["{7C9DD5BE-DCE3-4A5B-889C-EF3CD7A754DC}"]
   function GetData: integer;
 end;

 TClass1 = class(TNoRefrencedObject, IInterface1)
 private
   FData: integer;
 public
   function GetData: integer;
 end;

 IInterface2 = interface
 ["{B1E31834-213D-4519-AC3B-5A5C278006B6}"]
   function GetInterface1(AIndex: integer): IInterface1;
 end;

 TClass2 = class(TBaseListClass, IInterface2)
 public
   function GetInterface1(AIndex: integer): IInterface1;
   destructor Destroy; override;
 end;

 IInterface3 = interface
 ["{3FB223AB-8EA5-46CB-B3F1-AB3CF5698F8B}"]
   function GetInterface2: IInterface2;
 end;

 TClass3 = class(TInterfacedObject, IInterface3)
 private
   FClass2: TClass2;
 public
   function GetInterface2: IInterface2;
   constructor Create;
   destructor Destroy; override;
 end;

implementation

{ TNoRefrencedObject }

function TNoRefrencedObject._AddRef: Integer;
begin
Result := -1
end;

function TNoRefrencedObject._Release: Integer;
begin
Result := -1
end;

function TNoRefrencedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
 Result := S_OK
else
 Result := E_NOINTERFACE
end;

{ TBaseListClass }

constructor TBaseListClass.Create;
begin
FItems := TStringList.Create;
end;

destructor TBaseListClass.Destroy;
begin
FItems.Free;
inherited;
end;

{ TClass1 }

function TClass1.GetData: integer;
begin
Result := FData
end;

{ TClass2 }

destructor TClass2.Destroy;
begin
 TClass1(FItems.Objects[0]).Free;
 inherited;
end;

function TClass2.GetInterface1(AIndex: integer): IInterface1;
begin
Result := TClass1(FItems.Objects[AIndex])
end;

{ TClass3 }

constructor TClass3.Create;
var
 cl1: TClass1;
begin
FClass2 := TClass2.Create;
cl1 := TClass1.Create;
cl1.FData := 555;
FClass2.FItems.AddObject("xxx", cl1)
end;

destructor TClass3.Destroy;
begin
FClass2.Free;
inherited Destroy;
end;

function TClass3.GetInterface2: IInterface2;
begin
Result := FClass2
end;

end.


и сам проект:

program Project1;
uses
 SysUtils,
 Unit1 in "Unit1.pas";

var
 _main: IInterface3;
 _int1: IInterface1;
 _data: integer;
begin
_main := TClass3.Create;
// если закоментарить следующую строку, то ошибки не будет
_int1 := _main.GetInterface2.GetInterface1(0);  
_int1 := nil;
_main := nil
end.


После выполнения кода (после убийства _main) происходит AV.
Подскажите где я не прав.


 
Иван Шихалев ©   (2005-05-18 17:47) [1]

После _int1 := nil, объект освобождается, поскольку _Release = -1


 
Иван Шихалев ©   (2005-05-18 17:49) [2]

Хотя... сорри, гоню


 
Семен Сорокин ©   (2005-05-18 17:53) [3]

если закоментарить строку
TClass1(FItems.Objects[0]).Free;
в деструкторе TClass2 то AV не возникает, но, имхо, тогда будет утечка памяти.

После _int1 := nil, объект не освобождается т.к. он унаследован от TNoRefrencedObject.


 
Shaman_Naydak;   (2005-05-18 19:35) [4]

Создается неявная переменная из-за _main.GetInterface2
И освобождаться она будет.. когда?.. прально.. уже на выходе из метода, когда объект тю-тю..
отсюда мораль.. смешивать подсчитываемые ссылки и неподситываемые не самая лучшая затея


 
Семен Сорокин ©   (2005-05-19 09:57) [5]


> Shaman_Naydak;   (18.05.05 19:35) [4]
> Создается неявная переменная из-за _main.GetInterface2
> И освобождаться она будет.. когда?.. прально.. уже на выходе
> из метода, когда объект тю-тю..


а здесь Вы не правы, потому как _main.GetInterface2 - возвращает неподсчитываемый интерфейс, вот код - ошибка та же:

var
 _main: IInterface3;
 _int1: IInterface1;
 _int2: IInterface2;
 _data: integer;
begin
 _main := TClass3.Create;
 _int2 := _main.GetInterface2;
 _int1 := _int2.GetInterface1(0);
 _data := _int1.GetData;
 _int1 := nil;
 _int2 := nil;
 _main := nil
end.



> отсюда мораль.. смешивать подсчитываемые ссылки и неподситываемые
> не самая лучшая затея

в даннолм случе с подсчитываемыми ссылками у сменяя только главный (IInterface3) интерфейс.

ЗЫ. Проблема осталась :(


 
Slym ©   (2005-05-19 11:03) [6]

TClass - Это указатель на объект
IInterface - Это указатель на указатель объекта!!!


 
Семен Сорокин ©   (2005-05-19 11:33) [7]


> Slym ©   (19.05.05 11:03) [6]
> TClass - Это указатель на объект
> IInterface - Это указатель на указатель объекта!!!

Что Вы хотите этим сказать?
TClass - это указатель на тип объекта, а IInterface - указатель на тип интерфейса


 
Shaman_Naydak;   (2005-05-19 17:51) [8]

Молодой человек, послушайте старого и мудрого человека...
Все дело в скрытых и неявных переменных!
Когда вы вызываете функцию, возвращающую интерфейс, то у вас
заводится стековая переменная, отвечающая за эту переменную.
А уж затем производится копирование в глобальную переменную, которую вы задали..
Вот если бы вы перенесли весь код в процедуру, а не в главной программе.. то у вас переменные стали бы локальными и у дельфи хватит ума не создавать по второй копии переменной для хранения интерфейса.. Ферштейн?
Другой способ решения вопроса - использование процедур с out параметром... тут тоже не будет стековых переменных...

И наконец.. не читайте до обеда советских газет..
то есть не используйте неразумно неподсчитываемые интерфейсы...!
За сим разрешите откланяться ;))


 
Семен Сорокин ©   (2005-05-19 18:17) [9]


> Shaman_Naydak;   (19.05.05 17:51) [8]

Благодарю, все понятно.


 
Slym ©   (2005-05-20 06:17) [10]


>_main := TClass3.Create;
> _main := nil;

Ты думаешь сдесь нет утечки памяти?... Есть!
Где ты ты вызываешь деструктор? Нигде!
Интерфейсы с подсчетом, сами себе деструктор вызывают когда RefCount=0

Obj (Экземпляр TClass)- Это указатель на объект, т.е. при передачи объекта (как результата функции, или входного параметра) используется указатель на объект.
(@Obj/Obj^)

Interface - Это указатель на указатель объекта, т.е. при передаче (как результата функции, или входного параметра) используется указатель на указаетель объекта.(@@Obj/Obj^^)

Посмотри Демосы QRegister


 
Семен Сорокин ©   (2005-05-20 11:50) [11]


> Slym ©   (20.05.05 06:17) [10]
>
> >_main := TClass3.Create;
> > _main := nil;
>
> Ты думаешь сдесь нет утечки памяти?... Есть!
> Где ты ты вызываешь деструктор? Нигде!
> Интерфейсы с подсчетом, сами себе деструктор вызывают когда
> RefCount=0


Думаю здесь нет :)) даже знаю, потому как
TClass3 = class(TInterfacedObject, IInterface3)

вопрос снят



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

Форум: "Corba";
Текущий архив: 2006.04.09;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.018 c
15-1141996436
oldman
2006-03-10 16:13
2006.04.09
SiS - материнки...


2-1143122160
my_sweet
2006-03-23 16:56
2006.04.09
записать текст из мемо в Stringgrid


1-1141886515
Михаил (Киров)
2006-03-09 09:41
2006.04.09
Нуль-модемное соединение


3-1139978243
Strech
2006-02-15 07:37
2006.04.09
значение полей по умолчанию


5-1129107610
denissoft
2005-10-12 13:00
2006.04.09
Помогите написать компонент с 2 полями TDataField





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский