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

Вниз

Почему есть утечка памяти при использовании интерфейсов?   Найти похожие ветки 

 
Суслик ©   (2005-06-24 12:59) [0]

Есть два метода


procedure Dummy1(const aI: IInterface);
begin
  // некая операция с aI
end;

procedure Dummy2(aI: IInterface);
begin
  // некая операция с aI
end;


При вызове Dummy1(TInterfaceObject.Create()) происходит утечка памяти т.к. не отрабатывает деструктор созданного объекта TInterfaceObject.

При вызове Dummy2(TInterfaceObject.Create())  все ок - деструктор отрабатывает корректно.

Это глюк delphi или мой?


 
Digitman ©   (2005-06-24 13:03) [1]


> Это глюк delphi или мой?


ни твой ни Делфи.

это - ФИЧА (а не баг и не "глюк")

при
const aI: IЧегоТоТам

инкремента интерф.ссылки НЕ происходит,

а при
< aI: IЧегоТоТам

происходит


 
Суслик ©   (2005-06-24 13:04) [2]


>  [1] Digitman ©   (24.06.05 13:03)

Да это понятно, что фича (cpu я тоже смотреть умею). Только:
1. она нигде не описана
2. она изрядно гадит жизнь (


 
Digitman ©   (2005-06-24 13:10) [3]


> она нигде не описана


описана.

в справке просто покопаться следует изрядно детальней ... ибо прямой ссылки нет ...


> она изрядно гадит жизнь


ой не ври)

достаточно знать и понимать, что при передаче по const Делфи-компайлер НЕ ответственен за работу со сч-ком ссылок, в то время как во 2-м упомянутом варианте делфи-компайлер вставляет неявный код инкремента (и, если требуется, - декремента) упомянутого сч-ка интерфейсной ссылки

попросту говоря, при const никаких неявных _addref, _release нет, в то время как в упомянутом ином случае они фигурируют (и вполне оправданно)


 
default ©   (2005-06-24 13:21) [4]

Суслик ©   (24.06.05 13:04) [2]
совершенно логично действует компилятор...


 
Digitman ©   (2005-06-24 13:31) [5]


> Суслик


а есть ведь еще вариант с

var Intf: IМойИнтерфейс

странно что ты не присовокупил  его к вопросу, ибо так же концептуален он


 
Суслик ©   (2005-06-24 14:01) [6]


>  [5] Digitman ©   (24.06.05 13:31)

такой вариант работает, есно я это проверил.
В справке про const скорее всего это есть. Но ... читай дальше

----------

... про логичность я бы не стал соглашаться.
Т.к. фактически объект будучи созданным выходит из scope и если дельфи декларирует подсчет ссылок, то это ее дело уничтожать интрефейсы. А то, что я сам решил при передаче в метод не делать подсчет ссылок, это дельфи волновать вообще говоря мало должно - его задача обеспечивать live scope (если уж дельфи за это взялся).


 
Digitman ©   (2005-06-24 14:15) [7]


> А то, что я сам решил при передаче в метод не делать подсчет
> ссылок, это дельфи волновать вообще говоря мало должно


совершенно верно.

и именно поэтому ты в ДАННОМ случае передаешь свой интерфейс как параметр как const-параметр.... и компилятор при этом НЕ делает никаких неведомых тебе "телодвижений", т.е. все что ты понаписал - полностью прогнозируемо и подконтрольно тебе.


 
Суслик ©   (2005-06-24 14:25) [8]

убрали бы они вообще нафиг из delphi подсчет ссылок, либо сделали нормальный garbage collection для интерфейсов. Все лучше было бы.


 
Игорь Шевченко ©   (2005-06-24 14:29) [9]

Суслик ©   (24.06.05 14:25) [8]


> либо сделали нормальный garbage collection для интерфейсов.


Java или C# тебе в руки.


 
Digitman ©   (2005-06-24 14:30) [10]


> Суслик ©   (24.06.05 14:25) [8]


> бы они вообще нафиг из delphi подсчет ссылок, либо сделали
> нормальный garbage collection для интерфейсов


а вот тут ты уже начал ужасную чушь пороть)

остановись, вникни, подумай над сабжем !

просмотри, к примеру, sconnect.pas ... остынь) ...
все в этом плане закономерно и правильно !

)


 
Digitman ©   (2005-06-24 14:32) [11]


> garbage collection для интерфейсов


галиматья полная.

что значит "сборка мусора для интерфейсов" ?

НЕТ в списке существующих где-то там интерфейсов МУСОРА !


 
Суслик ©   (2005-06-24 14:37) [12]


>  [11] Digitman ©   (24.06.05 14:32)

ладно, давай без всяких там слов "галиматься" и пр.

------------

что будет здесь (ответь не пробуя, только честно)?

procedure e;
begin
  TInterfacedObject.Create();
end;


 
Digitman ©   (2005-06-24 14:48) [13]


> что будет здесь (ответь не пробуя, только честно)?


конкретно здесь (т.е. при вызове ДАННОЙ процедуры откуда бы то ни было) будет утечка.

тут и "пробовать" ничего не нужно - ты создал объект - экземпляр класса - потерял его адрес в памяти и уничтожить впоследствии, не имея адреса, разумеется не можешь.

класс объекта в дан.случае совершенно неважен.


 
Суслик ©   (2005-06-24 14:50) [14]


> [10] Digitman ©   (24.06.05 14:30)


> просмотри, к примеру, sconnect.pas ... остынь) ...

Ну да, они все делают через дополнительную локальную переменную:

function TDataBlockInterpreter.CallGetServerList: OleVariant;
var
 Flags: TVarFlags;
 Data: IDataBlock;
begin
 Data := TDataBlock.Create as IDataBlock;
 Data.Signature := CallSig or asGetAppServers;
 Data := FSendDataBlock.Send(Data, True);
 Result := ReadVariant(Flags, Data);
end;


А, кстати, насчет того, что сборка мусора здесь ни при чем я с трудом могу с тобой согласиться. Зачем сделан посчет ссылок? (если не ошибаюсь в ++ его нет). Для того, чтобы было удобно. Но по факту получается так, что приходится помнить условия, при которых подсчет работает верно. Приведенный мной пример не единственный.


 
Суслик ©   (2005-06-24 14:52) [15]


>  [13] Digitman ©   (24.06.05 14:48)

Согласен, это я что-то налажал :)


 
Суслик ©   (2005-06-24 14:57) [16]


> [13] Digitman ©   (24.06.05 14:48)


Ладно, закрыто.

Просто запомню, что в данном случае нужно быть осторожней с const.


 
Digitman ©   (2005-06-24 15:03) [17]


> Ну да, они все делают через дополнительную локальную переменную


врешь)

цитирую :

function TStreamedConnection.Send(const Data: IDataBlock; WaitForResult: Boolean): IDataBlock;
var
 Msg: TMsg;
 Context: Integer;
begin
 if FSupportCallbacks then
 begin
   if not Assigned(FTransport) then Exit;
   Data._AddRef;
   PostThreadMessage(FTransport.ThreadID, THREAD_SENDSTREAM, Ord(WaitForResult),
     Integer(Pointer(Data)));
...



> насчет того, что сборка мусора здесь ни при чем я с трудом
> могу с тобой согласиться. Зачем сделан посчет ссылок?


КАКОЕ отношение имеет механизм подсчета интерф.ссылок к т.н. "сборке мусора" ?

изложи свое вИденье ...


> Для того, чтобы было удобно


Да, конечно.

Мне, к примеру, неудобно, объявив в п/программе лок.переменную MyInterface типа ISomeInterface, заботиться о разрушении объекта, на который в ходе работы моей п/программы эта переменная ВОЗМОЖНО будет ссылаться. а возможно и НЕ будет.

И я с полным пониманием происходящего доверяюсь компилятору, который в ДАННОМ случае вставит неявный код
MyInterface := nil
который , если ссылка <> nil, вызовет за меня, лентяя, метод ISomeInterface._Release, что приведет к разрушению интерф.объекта, если декремент сч-ка в этот момент приведет к нулевому его значению.


 
Суслик ©   (2005-06-24 15:06) [18]


>  [17] Digitman ©   (24.06.05 15:03)

Речь была про ВЫЗЫВАЮЩУЮ сторону. Я тебе ее процитировал. Т.е. если я не хочу, чтобы у меня в исходном примере были ошибки, то я должен делать также как они.


 
Digitman ©   (2005-06-24 15:19) [19]


> Суслик ©   (24.06.05 15:06) [18]



> Речь была про ВЫЗЫВАЮЩУЮ сторону


ок.

вызывающая сторона, зная прототип ф-ции с неким интерфейсным параметром (IUnknown или его произвольным наследником) в том или ином виде, обязана иметь четкое представление о том как поступит компилятор.

в случае const или var компилятор НЕ генерирует неявного кода вызова методов _AddRef, _Release передаваемого интерф.объекта

в противном случае компилятор генерирует неявный вызов _AddRef  в контексте "открывающего" п/программу оператора begin и неявный вызов _Release в контексте "закрывающего" п/программу оператора end



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

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

Наверх




Память: 0.52 MB
Время: 0.043 c
1-1118093186
Lenka
2005-06-07 01:26
2005.07.11
перемещение обектов


14-1117995289
Cerberus
2005-06-05 22:14
2005.07.11
У кого есть фотка салюта.


1-1119346635
Гость233
2005-06-21 13:37
2005.07.11
Отловить появляение вертикальной полосы прокрутки в TListView


14-1118861856
yaJohn
2005-06-15 22:57
2005.07.11
хостинг с условиями


14-1118415727
default
2005-06-10 19:02
2005.07.11
Пятничная задачка