Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Работа с указателями [D6, WinXP]


SkyRanger ©   (2006-06-30 01:35:00) 

Подскажите нужно ли явно чистить память. Есть нормально работающий код:

Это чтобы не было вопросов что откуда берется:


TGLCollection = array [0..ENGINE_MAX_POINTERS] of Pointer;

TGLManager = class
protected
 FCollection       : TGLCollection;
 FPython           : TPython;
 FCount            : Integer;
 FIsActiveControls : Boolean;

 public
   procedure Add(); virtual; abstract;
   property Count : Integer read FCount write FCount;
end;

TGLWindowsManager = class (TGLManager)
...
end;

function TGLWindowsManager.Add(WinSkinPrefix:String;
var
CurrWin  : TGLWindow;
WRec  : TGLWindowRec;
begin

FCollection[FCount]:=TGLWindow.Create(WinSkinPrefix,
                  BorderWidth,BorderHeight,HeaderHeight,
TGLWindow(FCollection[FCount]).WindowName:=WinName;
TGLWindow(FCollection[FCount]).WinIndex:=FCount;
TGLWindow(FCollection[FCount]).WindowType:=GL_NORMAL_WINDOW;
Result:=FCount;

Inc(FCount);

end;


И собственно код:


procedure TGLWindowsManager.DrawById(WinId:Integer);
var
 I:Integer;
 CurrWin : TGLWindow;
begin
 for I:=0 to FCount-1 do
 begin
   CurrWin:=TGLWindow(FCollection[I]);
   if CurrWin.WinIndex=WinID then
     if CurrWin.Visible=1 then
       begin
         TGLWindow(FCollection[I]).Draw;
         if Trim(CurrWin.pyFuncName)<>'' then
           FPython.CallFuncByName(PChar(CurrWin.pyFuncName),nil);
       exit;
     end;
 end;
end;


Вопрос такой:
А надо ли что нить делать с CurrWin в самом конце функции. Т.е. возможна ли тут утечка памяти.
Просто пытаюсь найти откуда у меня в сукунду 4 или 8 байт утечка памяти. Сначала думал на Питон, но вроде разобрался с ним и на 4 мега удалось уменьшить занимаемую ядром память. Теперь вот думаю может тут собака порылась? :)


SkyRanger   (2006-07-04 05:02:00) [1]

Нашел утечку :)
Не пойму правда почему. Судя по Питоновскому хелпу все делаю правильно :(

//====================================================================

procedure pySetDoubleToObject(PyObj : PPyObject; ObjName:PChar; Value:Double;
                             CalledFrom : String);
var
 P:PPyObject;
begin
P:=PyFloat_FromDouble(Value);
 PyObject_SetAttrString(PyObj, ObjName, P);
 PyErrorCheckExt(P, 'pySetDoubleToObject: '+ObjName+chr(10)+
                   'Called from: '+CalledFrom);
 Py_XDECREF(P);
end;

//====================================================================

procedure pySetLongToObject(PyObj : PPyObject; ObjName:PChar; Value:Integer;
                             CalledFrom : String);
var
 P:PPyObject;
begin
 P:=PyLong_FromLong(Value);
PyObject_SetAttrString(PyObj, ObjName, P);
 PyErrorCheckExt(P, 'pySetLongToObject: '+ObjName+chr(10)+
                   'Called from: '+CalledFrom);
 Py_XDECREF(P);
end;

//====================================================================

procedure pySetStringToObject(PyObj : PPyObject; ObjName:PChar; Value : PChar;
                             CalledFrom : String);
var
 P:PPyObject;
begin
 P:=PyString_FromString(Value);
 PyObject_SetAttrString(PyObj, ObjName, P);
 PyErrorCheckExt(P, 'pySetStringToObject: '+ObjName+chr(10)+
                   'Called from: '+CalledFrom);
 Py_XDECREF(P);
end;


Германн   (2006-07-04 02:18:00) [2]


> Это не аргумент, а констатация факта :)

Это не констатация факта. Это "отмазка"! (В лучшем случае).


SkyRanger   (2006-07-04 00:57:00) [3]

Это не аргумент, а констатация факта :)


Игорь Шевченко   (2006-07-03 15:15:00) [4]


> Просто код не мой я сразу сказал


Кого-то из отвечающих ? Если нет, то почему ты это приводишь, как аргумент ?


SkyRanger   (2006-07-03 09:57:00) [5]

Хммм...
Я гляну.. Просто код не мой я сразу сказал :)


evvcom   (2006-07-03 09:16:00) [6]

Индекс ты считаешь с нуля правильно, но переменные FMethodsCount, FAllocatedMethodCount используешь нелогично. Судя по их названию - это количество элементов, оно на 1 больше, чем индекс последнего эл-та. Поэтому

>   Inc( FAllocatedMethodCount, PYT_METHOD_BUFFER_INCREASE);
>   ReAllocMem( FMethods, SizeOf(PyMethodDef)*(FAllocatedMethodCount +1)); // нелогично!
> MethodPtr :=@(PMethodArray(FMethods)^[FMethodsCount +1]); // нелогично!
...
> Result:=MethodsIdx[FMethodsCount]; // А здесь логичным было бы FMethodsCount - 1

Явных ошибок вроде не заметил, но путаница с индексами... Ты уж определись, или ты называешь переменные "Count" и используешь их как количество, или так как используешь, но переменные переименовываешь в "LastIndex".


ЮЮ   (2006-07-03 07:36:00) [7]


> Если снять комментарий, то появляется обшибка Access violation.
> Не пойму почему :( Если закоментировать то все ок.


Да уж, AV на сравнении 2х integer. В принципе возможно, если исользовать конструкцию TPyMethods.AddMethod, но чтобы при этом работали остальные строки метода ???


SkyRanger   (2006-07-03 04:21:00) [8]

> [6] Юрий Зотов ©   (03.07.06 02:12)

Хмм... Это идея надо будет покопаться :)


SkyRanger   (2006-07-03 04:19:00) [9]

Вот класс, он основан на коде от http://mmm-experts.com/
Я оставил только то что нужно, а принцип остался тот же.
Так вот в методе TPyMethods.AddMethod закоментированно условие.
Если снять комментарий, то появляется обшибка Access violation.
Не пойму почему :( Если закоментировать то все ок.

MemCheck ругается на утечку в строке
   ReAllocMem( FMethods, SizeOf(PyMethodDef)*(FAllocatedMethodCount+1));
даже не на утечку, просто сам мемчек дает ошибку у себя в коде...

Вот мне и интересно что тут может быть неправильно :(



 TMethodArray = array[ 0 .. 16000 ] of PyMethodDef;
 PMethodArray = ^TMethodArray;

//--------------------------------------------------------
//--                                                    --
//-- class:  TPyMethods                                 --
//-- Methods to be called inside Python script and      --
//-- Module for import inside Python script             --
//--------------------------------------------------------

 TPyMethods = class
 private
   FMethods              : PPyMethodDef;
   FMethodsCount         : Integer;
 FAllocatedMethodCount : Integer;

 function GetMethod( Index : Integer ) : PPyMethodDef;

 public
   constructor Create;
   destructor Destroy;  override;

   function AddMethod( AMethodName : PChar;
                       AMethod  : PyCFunction;
                       ADocString : PChar ) : PPyMethodDef;
   property Methods : PPyMethodDef read FMethods write FMethods;
   property MethodsIdx[ idx : Integer ] : PPyMethodDef read GetMethod;
 end;

{TPyMethods}

constructor TPyMethods.Create;
begin
   Assert(FMethods = nil);
   FAllocatedMethodCount:=PYT_METHOD_BUFFER_INCREASE;
   FMethodsCount:=0;
   FMethods:=PPyMethodDef(AllocMem(SizeOf(PyMethodDef)*(FAllocatedMethodCount+1)));
   FillChar(FMethods^, Sizeof(FMethods^)*FAllocatedMethodCount, 0);
end;

//--------------------------------------------------------------------

destructor TPyMethods.Destroy;
begin
 if Assigned(FMethods) then
 begin
   FreeMem(FMethods);
   FMethods := nil;
 end;
 FAllocatedMethodCount := 0;
 FMethodsCount := 0;
end;

//--------------------------------------------------------------------

function TPyMethods.GetMethod( Index : Integer ) : PPyMethodDef;
begin
 if (Index < 0) or (Index > FMethodsCount) then
   raise Exception.CreateFmt('%s: Index %d out of range', [ClassName, Index]);
 Result := @( PMethodArray(FMethods)^[Index] );
end;

function TPyMethods.AddMethod( AMethodName : PChar;
                              AMethod  : PyCFunction;
                              ADocString : PChar ) : PPyMethodDef;
var
 MethodPtr : PPyMethodDef;
begin
//  if FMethodsCount = FAllocatedMethodCount then
 begin
   Inc( FAllocatedMethodCount, PYT_METHOD_BUFFER_INCREASE );
   ReAllocMem( FMethods, SizeOf(PyMethodDef)*(FAllocatedMethodCount+1));
   MethodPtr :=@(PMethodArray(FMethods)^[FMethodsCount+1]);
   FillChar( MethodPtr^,SizeOf(PyMethodDef)*PYT_METHOD_BUFFER_INCREASE,0);
 end;
 Result:=MethodsIdx[FMethodsCount];
 Result^.ml_meth:=PyCFunction(AMethod);
 Result^.ml_name:=AMethodName;
 Result^.ml_doc:=ADocString;
 Result^.ml_flags := METH_VARARGS;
 Inc(FMethodsCount);
end;


Юрий Зотов   (2006-07-03 02:12:00) [10]

> а в деструкторе освобождается...

Это в деструкторе НАПИСАНО, что она освобождается. А РЕАЛЬНО она будет освобождаться только если этот деструктор действительно вызывается.

А если нет?
:о)

Например, в объявлении деструктора пропущено override. Или просто где-то банально не уничтожается уже ненужный объект.


Джо   (2006-07-03 01:28:00) [11]

> [4] SkyRanger ©   (03.07.06 01:01)
> Насчет Memcheck - он мне находит утечек 62 штуки, при этом
> там, где на мой взгляд все ок. Т.е. память в конструкторе
> выделяется, а в деструкторе освобождается...
> Он всегда точно показывает или как получится???

У меня ни разу ложных срабатываний не наблюдалось...


SkyRanger   (2006-07-03 01:01:00) [12]

Насчет Memcheck - он мне находит утечек 62 штуки, при этом там, где на мой взгляд все ок. Т.е. память в конструкторе выделяется, а в деструкторе освобождается...
Он всегда точно показывает или как получится???


Джо   (2006-06-30 03:09:00) [13]

Погоняй с MemCheck ( http://v.mahon.free.fr/pro/freeware/memcheck) или FastMM ( http://fastmm.sourceforge.net). Рекоммендую для отладки первый.


SkyRanger   (2006-06-30 02:59:00) [14]

Хммм... Спасибо. Тоды буду копаться дальше. Должна же где то не освобождаться память. И скорее косяк с указателем раз стабильно утечка по 4 или 8 байт. Ну по восемь не обязательно. Может быть просто очень быстро по 4, просто винда не показывает... :(


Германн   (2006-06-30 01:41:00) [15]


> А надо ли что нить делать с CurrWin в самом конце функции.

Нет. Это просто локальная переменная размером в 4 байта, которой при входе в метод было "выделено" пространство в стеке, а при выходе "изъято".


Наверх

Титульная страница Поиск, карта сайта Написать письмо