Текущий архив: 2005.07.11;
Скачать: CL | DM;
Вниз
Почему есть утечка памяти при использовании интерфейсов? Найти похожие ветки
← →
Суслик © (2005-06-24 12:59) [0]Есть два метода <br/><br/><code><br/>procedure Dummy1(const aI: IInterface);<br/>begin<br/>   // некая операция с aI<br/>end;<br/><br/>procedure Dummy2(aI: IInterface);<br/>begin<br/>   // некая операция с aI<br/>end;<br/></code><br/><br/>При вызове Dummy1(TInterfaceObject.Create()) происходит утечка памяти т.к. не отрабатывает деструктор созданного объекта TInterfaceObject. <br/><br/>При вызове Dummy2(TInterfaceObject.Create())  все ок - деструктор отрабатывает корректно. <br/><br/>Это глюк delphi или мой?
← →
Digitman © (2005-06-24 13:03) [1]<i><br/>> Это глюк delphi или мой?<br/></i><br/><br/>ни твой ни Делфи.<br/><br/>это - ФИЧА (а не баг и не "глюк")<br/><br/>при<br/><u><b>const</b> aI: IЧегоТоТам</u><br/><br/>инкремента интерф.ссылки НЕ происходит,<br/><br/>а при<br/><u>< aI: IЧегоТоТам</u><br/><br/>происходит
← →
Суслик © (2005-06-24 13:04) [2]<i><br/>>  [1] Digitman ©   (24.06.05 13:03)<br/></i><br/>Да это понятно, что фича (cpu я тоже смотреть умею). Только:<br/>1. она нигде не описана<br/>2. она изрядно гадит жизнь (
← →
Digitman © (2005-06-24 13:10) [3]<i><br/>> она нигде не описана<br/></i><br/><br/>описана.<br/><br/>в справке просто покопаться следует изрядно детальней ... ибо прямой ссылки нет ...<br/><br/><i><br/>> она изрядно гадит жизнь <br/></i><br/><br/>ой не ври)<br/><br/>достаточно знать и понимать, что при передаче по const Делфи-компайлер НЕ ответственен за работу со сч-ком ссылок, в то время как во 2-м упомянутом варианте делфи-компайлер вставляет неявный код инкремента (и, если требуется, - декремента) упомянутого сч-ка интерфейсной ссылки<br/><br/>попросту говоря, при const никаких неявных _addref, _release нет, в то время как в упомянутом ином случае они фигурируют (и вполне оправданно)
← →
default © (2005-06-24 13:21) [4]Суслик ©   (24.06.05 13:04) [2] <br/>совершенно логично действует компилятор...
← →
Digitman © (2005-06-24 13:31) [5]<i><br/>> Суслик<br/></i><br/><br/>а есть ведь еще вариант с <br/><br/>var Intf: IМойИнтерфейс<br/><br/>странно что ты не присовокупил  его к вопросу, ибо так же концептуален он
← →
Суслик © (2005-06-24 14:01) [6]<i><br/>>  [5] Digitman ©   (24.06.05 13:31)<br/></i><br/>такой вариант работает, есно я это проверил. <br/>В справке про const скорее всего это есть. Но ... читай дальше<br/><br/>----------<br/><br/>... про логичность я бы не стал соглашаться. <br/>Т.к. фактически объект будучи созданным выходит из scope и если дельфи декларирует подсчет ссылок, то это ее дело уничтожать интрефейсы. А то, что я <b>сам решил при передаче</b> в метод не делать подсчет ссылок, это дельфи волновать вообще говоря мало должно - его задача обеспечивать live scope (если уж дельфи за это взялся).
← →
Digitman © (2005-06-24 14:15) [7]<i><br/>> А то, что я сам решил при передаче в метод не делать подсчет <br/>> ссылок, это дельфи волновать вообще говоря мало должно <br/></i><br/><br/>совершенно верно.<br/><br/>и именно поэтому ты в ДАННОМ случае передаешь свой интерфейс как параметр как const-параметр.... и компилятор при этом НЕ делает никаких неведомых тебе "телодвижений", т.е. все что ты понаписал - полностью прогнозируемо и подконтрольно тебе.
← →
Суслик © (2005-06-24 14:25) [8]убрали бы они вообще нафиг из delphi подсчет ссылок, либо сделали нормальный garbage collection для интерфейсов. Все лучше было бы.
← →
Игорь Шевченко © (2005-06-24 14:29) [9]Суслик ©   (24.06.05 14:25) [8] <br/><br/><i><br/>> либо сделали нормальный garbage collection для интерфейсов.<br/></i><br/><br/>Java или C# тебе в руки.
← →
Digitman © (2005-06-24 14:30) [10]<i><br/>> Суслик ©   (24.06.05 14:25) [8] <br/></i><br/><i><br/>> бы они вообще нафиг из delphi подсчет ссылок, либо сделали <br/>> нормальный garbage collection для интерфейсов<br/></i><br/><br/>а вот тут ты уже начал ужасную чушь пороть)<br/><br/>остановись, вникни, подумай над сабжем !<br/><br/>просмотри, к примеру, sconnect.pas ... остынь) ... <br/>все в этом плане закономерно и правильно !<br/><br/>)
← →
Digitman © (2005-06-24 14:32) [11]<i><br/>> garbage collection для интерфейсов<br/></i><br/><br/>галиматья полная.<br/><br/>что значит "сборка мусора для интерфейсов" ?<br/><br/>НЕТ в списке существующих где-то там интерфейсов МУСОРА !
← →
Суслик © (2005-06-24 14:37) [12]<i><br/>>  [11] Digitman ©   (24.06.05 14:32)<br/></i><br/>ладно, давай без всяких там слов "галиматься" и пр. <br/><br/>------------<br/><br/>что будет здесь (ответь не пробуя, только честно)?<br/><br/><code>procedure e;<br/>begin<br/>   TInterfacedObject.Create();<br/>end;</code>
← →
Digitman © (2005-06-24 14:48) [13]<i><br/>> что будет здесь (ответь не пробуя, только честно)?<br/></i><br/><br/>конкретно здесь (т.е. при вызове ДАННОЙ процедуры откуда бы то ни было) будет утечка.<br/><br/>тут и "пробовать" ничего не нужно - ты создал объект - экземпляр класса - потерял его адрес в памяти и уничтожить впоследствии, не имея адреса, разумеется не можешь.<br/><br/>класс объекта в дан.случае совершенно неважен.
← →
Суслик © (2005-06-24 14:50) [14]<i><br/>> [10] Digitman ©   (24.06.05 14:30)<br/></i><br/><i><br/>> просмотри, к примеру, sconnect.pas ... остынь) ... <br/></i><br/>Ну да, они все делают через дополнительную локальную переменную:<br/><br/><code>function TDataBlockInterpreter.CallGetServerList: OleVariant;<br/>var<br/>  Flags: TVarFlags;<br/>  Data: IDataBlock;<br/>begin<br/>  Data := TDataBlock.Create as IDataBlock;<br/>  Data.Signature := CallSig or asGetAppServers;<br/>  Data := FSendDataBlock.Send(Data, True);<br/>  Result := ReadVariant(Flags, Data);<br/>end;</code><br/><br/>А, кстати, насчет того, что сборка мусора здесь ни при чем я с трудом могу с тобой согласиться. Зачем сделан посчет ссылок? (если не ошибаюсь в ++ его нет). Для того, чтобы было удобно. Но по факту получается так, что приходится помнить условия, при которых подсчет работает верно. Приведенный мной пример не единственный.
← →
Суслик © (2005-06-24 14:52) [15]<i><br/>>  [13] Digitman ©   (24.06.05 14:48)<br/></i><br/>Согласен, это я что-то налажал :)
← →
Суслик © (2005-06-24 14:57) [16]<i><br/>> [13] Digitman ©   (24.06.05 14:48)<br/></i><br/><br/>Ладно, закрыто. <br/><br/>Просто запомню, что в данном случае нужно быть осторожней с const.
← →
Digitman © (2005-06-24 15:03) [17]<i><br/>> Ну да, они все делают через дополнительную локальную переменную<br/></i><br/><br/>врешь)<br/><br/>цитирую :<br/><br/><code>function TStreamedConnection.Send(<b>const</b> Data: IDataBlock; WaitForResult: Boolean): IDataBlock;<br/>var<br/>  Msg: TMsg;<br/>  Context: Integer;<br/>begin<br/>  if FSupportCallbacks then<br/>  begin<br/>    if not Assigned(FTransport) then Exit;<br/>    Data._AddRef;<br/>    PostThreadMessage(FTransport.ThreadID, THREAD_SENDSTREAM, Ord(WaitForResult),<br/>      Integer(Pointer(Data)));<br/>...</code><br/><br/><i><br/>> насчет того, что сборка мусора здесь ни при чем я с трудом <br/>> могу с тобой согласиться. Зачем сделан посчет ссылок?<br/></i><br/><br/>КАКОЕ отношение имеет механизм подсчета интерф.ссылок к т.н. "сборке мусора" ?<br/><br/>изложи свое вИденье ...<br/><br/><i><br/>> Для того, чтобы было удобно<br/></i><br/><br/>Да, конечно.<br/><br/>Мне, к примеру, неудобно, объявив в п/программе лок.переменную MyInterface типа ISomeInterface, заботиться о разрушении объекта, на который в ходе работы моей п/программы эта переменная ВОЗМОЖНО <u>будет</u> ссылаться. а возможно и <u>НЕ будет</u>.<br/><br/>И я с полным пониманием происходящего доверяюсь компилятору, который в ДАННОМ случае вставит неявный код <br/>MyInterface := nil<br/>который , если ссылка <> nil, вызовет за меня, лентяя, метод ISomeInterface._Release, что приведет к разрушению интерф.объекта, если декремент сч-ка в этот момент приведет к нулевому его значению.
← →
Суслик © (2005-06-24 15:06) [18]<i><br/>>  [17] Digitman ©   (24.06.05 15:03)<br/></i><br/>Речь была про ВЫЗЫВАЮЩУЮ сторону. Я тебе ее процитировал. Т.е. если я не хочу, чтобы у меня в исходном примере были ошибки, то я должен делать также как они.
← →
Digitman © (2005-06-24 15:19) [19]<i><br/>> Суслик ©   (24.06.05 15:06) [18] <br/></i><br/><br/><i><br/>> Речь была про ВЫЗЫВАЮЩУЮ сторону<br/></i><br/><br/>ок.<br/><br/>вызывающая сторона, зная прототип ф-ции с неким интерфейсным параметром (IUnknown или его произвольным наследником) в том или ином виде, обязана иметь четкое представление о том как поступит компилятор.<br/><br/>в случае const или var компилятор <b>НЕ</b> генерирует неявного кода вызова методов _AddRef, _Release передаваемого интерф.объекта<br/><br/>в противном случае компилятор генерирует <u>неявный</u> вызов _AddRef  в контексте "открывающего" п/программу оператора <b>begin</b> и <u>неявный</u> вызов _Release в контексте "закрывающего" п/программу оператора <b>end</b>
Страницы: 1 вся ветка
Текущий архив: 2005.07.11;
Скачать: CL | DM;
Память: 1.32 MB
Время: 0.037 c