Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Технологии
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 28.03.2012, 12:49
Аватар для vvvch
vvvch vvvch вне форума
Прохожий
 
Регистрация: 28.03.2012
Адрес: г.Боровичи, Новг. обл.
Сообщения: 19
Версия Delphi: Lazarus
Репутация: 10
По умолчанию Память и OPC

Нужно ли уничтожать объекты (.NET - технологией не пользуюсь, "уборки мусора" нет) возвращенные интерфейсами OPC (IOPCServerList, IOPCBrowseServerAddressSpase и др.)? (Скорее всего нужно.) Данные функции возвращают IEnumString - его уничтожать надо? И какими функциями это делать? (Все возможные лучше с кратким описанием для чего ини нужны?) Я знаю одну (CoTaskMemFree - но для чего она и как её применять - не знаю). Кто занимался этой проблемой - помогите. Особенно заботят утечки памяти от IOPCSyncIO, IOPCAsyncIO - если клиент будет работать долго - то это опасно. (PResultList и т.д. как уничтожить?) (Как уничтожить возвращенные объекты IStrindList и IResultList и другие.)
Заранее спасибо за ответ.
Ответить с цитированием
  #2  
Старый 28.03.2012, 17:12
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Интерфейсы в Дельфи - это объекты с управляемым временем жизни.
То есть с переменными любого типа, отнаследованого от TInterface, Дельфи поступает так.

1) если в процедуре описана переменная интерфейсного типа, то перед первым оператором процедуры эта переменная получает значение Nil;
2) у каждого объекта, реализующего какой-нибудь интерфейс обязательно должны быть две функции - AddRef и Release. Как правило, объект при вызове AddRef должен увеличить внутренний счётчик, при вызове Release - уменьшить. Если при этом значение счётчика станет равным нулю, то объект вызывает свой деструктор. То есть правильно реализованый COM-объект сам следит за своим временем жизни.
Теперь синтаксический сахар
3) если A - переменная интерфейсного типа, а Exp - некое выражение, вырабатывающее интерфейс (переменная или вызов функции), то за оператором присваивания
Код:
 A:=Exp; 
стоит примерно такая процедура
Код:
 
  if A<>Nil then A.Release(); // этот код Дельфи добавляет сама
  A:=Exp; 
  if A<>Nil then A.AddRef(); // этот код Дельфи добавляет сама
4) а в конце процедуры вызываются Release для всех таких переменных
5) кроме того, если в Record-е есть поля интерфейсного типа, то инициализация и финализация применяется и к ним.

Что бы избавиться от интерфейса, достаточно переменной присвоить nil.

То есть если не использовать явные приведения к Pointer и не использовать move и ему подобные ухищрения, то Дельфи всё сделает за Вас.
Удачи
Ответить с цитированием
  #3  
Старый 29.03.2012, 08:44
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Код:
  IInterface = interface
    ['{00000000-0000-0000-C000-000000000046}']
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
  end;
  IUnknown = IInterface;
а так да, при потере области видимости компилятор неявно вызовет _Release.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #4  
Старый 29.03.2012, 10:35
Аватар для vvvch
vvvch vvvch вне форума
Прохожий
 
Регистрация: 28.03.2012
Адрес: г.Боровичи, Новг. обл.
Сообщения: 19
Версия Delphi: Lazarus
Репутация: 10
По умолчанию

Еще раз спасибо отвившим, эта тема очень вскользь описана и ответов я пока не нашёл. В общем, как я понимаю, для того, чтобы освободить память мне достаточно переменной интерфейсного типа присвоить nil? Остальное сделает сама Delphi?
Но я провёл эксперимент:
procedure TForm1.FormCreate(Sender: TObject);
var
Mem : _MEMORYSTATUS;
RetMem : Cardinal;

//R:HRESULT;
B:IOPCBrowseServerAddressSpace;
Ser:IOPCServer;
I:IDispatch;
pEnum:IEnumString;
S:String;
pS,ItemID : POleStr;
L:Longint;
begin
//R := CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
//OutputDebugString(PChar(Format('%d',[R])));
GlobalMemoryStatus(Mem);
RetMem := Mem.dwAvailVirtual;
OutputDebugString(PChar(Format('Свободная память: %d',[RetMem - Mem.dwAvailVirtual])));

//CoGetMalloc(1, Ser);
Ser:=CreateComObject(ProgIDToClassID('dOPCSim.Kass l.Simulation')) as IOPCServer;
GlobalMemoryStatus(Mem);
OutputDebugString(PChar(Format('Память после создания сервера: %d',[RetMem - Mem.dwAvailVirtual])));

(*Ser.QueryInterface(IID_IOPCBrowseServerAddressSp ace,B);
GlobalMemoryStatus(Mem);
OutputDebugString(PChar(Format('Память после создания В: %d',[RetMem - Mem.dwAvailPhys])));

B.BrowseOPCItemIDs(OPC_BRANCH{OPC_LEAF},'',VT_EMPT Y,0,pEnum);
GlobalMemoryStatus(Mem);
OutputDebugString(PChar(Format('Память после создания перечисления: %d',[RetMem - Mem.dwAvailPhys])));

//OutputDebugString(PChar(Format('%d',[R])));
//CoTaskMemFree(pEnum);

{pEnum.Next(1,pS,@L);
S := pS;
OutputDebugString(PChar(Format('%s : %d',[S,L])));

B.GetItemID(pS,ItemID);
OutputDebugString(PChar(Format('%s',[ItemID])));

pEnum.Next(1,pS,@L);
S := pS;
OutputDebugString(PChar(Format('%s : %d',[S,L])));

B.GetItemID(pS,ItemID);
OutputDebugString(PChar(Format('%s',[ItemID])));}

B := Nil;*)
{ CoGetMalloc(1, cntMalloc);
if Assigned(ppServerStatus.szVendorInfo) then
cntMalloc.Free(ppServerStatus.szVendorInfo);
if Assigned(ppServerStatus) then
cntMalloc.Free(ppServerStatus);}
//Ser.;
Ser := Nil;
GlobalMemoryStatus(Mem);
OutputDebugString(PChar(Format('Память в конце: %d',[RetMem - Mem.dwAvailVirtual])));
//CoUninitialize;
end;

Ипри завершении процедуры последний вызов GlobalMemoryStatus(Mem) не даёт нуля. Хотя переменной Ser я вроде бы nil присвоил. Пытался насыльно вызвать Ser._Release но добился исключения и завершения по ошибке. Короче мож я не то делаю, или ошибочно понимаю технологию создания и освобождения. Да первоначально вопрос был другой, о результатах вызова этих функции, и и от самих одъектов типа OPC сервера память надо освобождать, ибо они больщие (сотни килобайт). Короче я запутался...
Ответить с цитированием
  #5  
Старый 29.03.2012, 10:45
Аватар для vvvch
vvvch vvvch вне форума
Прохожий
 
Регистрация: 28.03.2012
Адрес: г.Боровичи, Новг. обл.
Сообщения: 19
Версия Delphi: Lazarus
Репутация: 10
По умолчанию

Код, что я отправил - работаюший. Но двихок сервера его изменил и сделал неверным, по этому я его отправляю еще раз...
Код:
procedure TForm1.FormCreate(Sender: TObject);
var
  Mem : _MEMORYSTATUS;
  RetMem : Cardinal;

  //R:HRESULT;
  B:IOPCBrowseServerAddressSpace;
  Ser:IOPCServer;
  I:IDispatch;
  pEnum:IEnumString;
  S:String;
  pS,ItemID : POleStr;
  L:Longint;
begin
  //R := CoInitializeEx(nil,COINIT_APARTMENTTHREADED);
  //OutputDebugString(PChar(Format('%d',[R])));
  GlobalMemoryStatus(Mem);
  RetMem := Mem.dwAvailVirtual;
  OutputDebugString(PChar(Format('Свободная память: %d',[RetMem - Mem.dwAvailVirtual])));

  //CoGetMalloc(1, Ser);
  Ser:=CreateComObject(ProgIDToClassID('dOPCSim.Kassl.Simulation')) as IOPCServer;
  GlobalMemoryStatus(Mem);
  OutputDebugString(PChar(Format('Память после создания сервера: %d',[RetMem - Mem.dwAvailVirtual])));

  (*Ser.QueryInterface(IID_IOPCBrowseServerAddressSpace,B);
  GlobalMemoryStatus(Mem);
  OutputDebugString(PChar(Format('Память после создания В: %d',[RetMem - Mem.dwAvailPhys])));

  B.BrowseOPCItemIDs(OPC_BRANCH{OPC_LEAF},'',VT_EMPTY,0,pEnum);
  GlobalMemoryStatus(Mem);
  OutputDebugString(PChar(Format('Память после создания перечисления: %d',[RetMem - Mem.dwAvailPhys])));

  //OutputDebugString(PChar(Format('%d',[R])));
  //CoTaskMemFree(pEnum);

  {pEnum.Next(1,pS,@L);
  S := pS;
  OutputDebugString(PChar(Format('%s : %d',[S,L])));

  B.GetItemID(pS,ItemID);
  OutputDebugString(PChar(Format('%s',[ItemID])));

  pEnum.Next(1,pS,@L);
  S := pS;
  OutputDebugString(PChar(Format('%s : %d',[S,L])));

  B.GetItemID(pS,ItemID);
  OutputDebugString(PChar(Format('%s',[ItemID])));}

  B := Nil;*)
  {  CoGetMalloc(1, cntMalloc);
  if Assigned(ppServerStatus.szVendorInfo) then
    cntMalloc.Free(ppServerStatus.szVendorInfo);
  if Assigned(ppServerStatus) then
    cntMalloc.Free(ppServerStatus);}
  //Ser.;
  Ser := Nil;
  GlobalMemoryStatus(Mem);
  OutputDebugString(PChar(Format('Память в конце: %d',[RetMem - Mem.dwAvailVirtual])));
  //CoUninitialize;
end;
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 20:19.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter