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

Вниз

Не правильное освобождение Menu   Найти похожие ветки 

 
vampir_infernal   (2006-12-10 20:24) [0]

Использую в своем проекте Menu: PMenu. Создаю, рабтаю с ним, пытаюсь уничтожить. Если уничтожать так:
destructor TfmMain.Destroy;
Free_And_Nil(Menu);
Free_And_Nil(Form);
inherited;
end;

то вылетает AV на неправильную работу с указателями. То же самое, если добавлять меню в AutoFree апплета или формы. Теперь меняем местами освобождение меню и формы в деструкторе. Прога закрывается нормально, но MemProof и сторонняя программа контроля памяти ругаются на неосвобожденные 56 байт (сторонняя программа) или 64 байта (MemProof). Бился я с этой проблемой примерно 2 часа. Потом написал следующее:
destructor TfmMain.Destroy;
Free_And_Nil(Form);
Menu.Free;
Menu := nil;
inherited;
end;

и все заработало как надо. Если это какая-то неточнось в системе уничтожения меню в KOL, то ее необходимо исправить. Если же это моя ошибка, то подскажите, что же я сделал не правильно и почему меню не хочет уничтожаться как все остальные контролы?


 
vampir_infernal   (2006-12-10 20:30) [1]

Открылись новые факты: все работает только с директивой PAS_VERSION. Без нее так же ругается не освобожденныу память.


 
SergeR ©   (2006-12-11 10:53) [2]

По теме:
Юзаю FastMM4 и MemProop. Они тоже ругаются на утечки памяти в проекте.
Для примера:
Создал новый KOL проект с пустой формой. Сохранил, запустил.
Оба менеджера ругаются на 40+16=56 байт не освобожденной памяти.
При добавлении на форму любых KOL компонентов объем "потерянной"
памяти увеличивается.


 
Vladimir Kladov   (2006-12-11 16:57) [3]

Начнем с того, что я не понял, что это такое:
destructor TfmMain.Destroy;
Free_And_Nil(Menu);
Free_And_Nil(Form);
inherited;
end;


Чистый KOL? Menu будет уничтожаться еще раз вместе с формой. Надо его отцепить RemoveFromAutoFree. В MCK первичен объект формы TControl, а не TObj, ее держащий. Соответственно, там надо уничтожать TControl, а он убьет держателя. А вы все делаете по-своему, не смотрите, что при этом делается, и хотите, чтобы заработало правильно.


 
vampir_infernal   (2006-12-11 19:11) [4]

Это чистый KOL. Я не добавлял меню в AutoFree. Еслу оно само туда каким-то образом добавляется, то я это учту. Спасибо за помощь.


 
Vladimir Kladov   (2006-12-12 15:19) [5]

Тогда уточните: меню главное? Если главное, то при присваивании форме точно присоединяется. Вообще, кода приведено мало.


 
SergeR ©   (2006-12-12 16:45) [6]


program Demo;
uses
 // FastMM4,
Windows, kol;
type
 PForm1 = ^TForm1;
 TForm1 = object(TObj)
   Form: PControl;
   MainMenu1: PMenu;
 public
 end;

procedure NewForm1( var Result: PForm1; AParent: PControl );
begin
 New( Result, Create );
 Result.Form := NewForm( AParent, "Demo" ).SetClientSize( 400, 400 );
 Result.Form.Add2AutoFree( Result );
 Result.MainMenu1 := NewMenu( Result.Form, 0, [ "Test"], nil );
end;

var
 Form1: PForm1;

begin
 Applet := NewApplet( "Test" );
 NewForm1( Form1, Pointer( Applet ) );
 Run( Applet );
end.

Вот на этот код FastMM4 и MemProof у меня ругаются


 
vampir_infernal   (2006-12-12 18:16) [7]

Это меню, которое появляется над иконкой в трее. Наследуется оно от панельки размером 1 на 1, потому что если наследовать от формы, то меню автоматически вешается под загаловок и становится главным. Вот весь код всего модуля. В таком виде все работает и мемпруф молчит.
unit unMain;

interface

uses windows, messages, kol;

const Capt = "Рассчет червячной передачи";

type
   PfmMain = ^ TfmMain;
   TfmMain = object( TObj )
   private
      Panel: PControl;
      Menu: PMenu;
      procedure ChToolTip(const Value: KOLstring);
      procedure DoTrayMouse(Sender: PObj; Message: Word);
      procedure DoWorkMenu(Sender: PMenu; Item: Integer);
      procedure FormOnMinimize(Sender: Pobj);
      procedure FormOnClose(Sender: PObj; var Accept: Boolean);
   public
      form: PControl;
      Tray: PTrayIcon;
      AcceptClose: boolean;
      constructor Create;
      destructor Destroy; virtual;
      procedure ShowAbout;
   end;

{$EXTERNALSYM ShellAbout}
function ShellAbout(Wnd: HWND; szApp, szOtherStuff: PChar; Icon: HICON): Integer; stdcall;

function NewFmMain : PfmMain;

implementation

function ShellAbout; external "shell32.dll" name "ShellAboutA";
{ TfmMain }

procedure TfmMain.ChToolTip(const Value: KOLstring);
var buf: KOLstring;
begin
 buf := value;
 if Length(buf) > 62 then
   buf := Copy(buf, 1, 62)
 else if Value <> "" then
   Tray.Tooltip := buf;
 buf := "";
end;

constructor TfmMain.Create;
begin
    form := NewForm(applet, Capt).SetPosition(200, 200).SetSize(600, 400);
    AcceptClose := False;
    form.Style := form.Style and not WS_MAXIMIZEBOX;
    form.SizeGrip := true;
    form.Visible := true;
    form.OnMinimize := FormOnMinimize;
    form.OnClose := FormOnClose;
    form.IconLoad(hInstance, "MAINICON");
    Panel := NewPanel(applet, esNone).SetSize(1, 1);
    menu := NewMenu(panel, 0, ["Очистить поля", "О программе", "-", "Выход", ""], DoWorkMenu);
    RemoveFromAutoFree(menu);
    Tray := NewTrayIcon(panel, applet.Icon);
    Tray.OnMouse := DoTrayMouse;
    Tray.Active := true;
    Tray.AutoRecreate := true;
    ChToolTip("Рассчет червячной передачи");
end;

destructor TfmMain.Destroy;
begin
    Free_And_Nil(Tray);
    Free_and_Nil(panel);
    Free_And_Nil(form);
    Menu.Free;
    Menu := nil;

    inherited;
end;

function NewFmMain: PfmMain;
begin
 New(Result, Create);
end;

procedure TfmMain.DoTrayMouse(Sender: PObj; Message: Word);
var
 P: TPoint;
begin
 case Message of
   WM_RBUTTONUP:
     begin
       SetForegroundWindow(form.Handle);
       GetCursorPos(P);
       Menu.PopUpEx(P.X, P.Y);
     end;
   WM_LBUTTONUP:
     begin
       form.WindowState := wsNormal;
       ShowWindow(FindWindow(nil, Capt), SW_SHOW);
       SetForegroundWindow(form.Handle);
     end;
 end;
 p := MakePoint(0,0);
end;

procedure TfmMain.DoWorkMenu(Sender: PMenu; Item: Integer);
begin
 case Item of
 //  0: CleanBoxes;
   1: ShowAbout;
   3: begin
        AcceptClose := true;
        PostMessage(Applet.Handle, WM_CLOSE, 0, 0);
      end;
 end;
end;

procedure TfmMain.FormOnClose(Sender: PObj; var Accept: Boolean);
begin
 if not AcceptClose then
   PControl(Sender).Visible := false;
   Accept := AcceptClose;
end;

procedure TfmMain.FormOnMinimize(Sender: Pobj);
begin
    PControl(Sender).WindowState := wsMinimized;
end;

procedure TfmMain.ShowAbout;
begin
     ShellAbout(applet.handle, PChar(Capt), PChar("bla"), applet.Icon);
end;

end.


 
Vladimir Kladov   (2006-12-12 18:49) [8]

Нет, не то. Кинулся искать баг, и нашел: в асм-версии действительно проблема в TObj.Final. Но меню ни при чем совершенно. Если просто закомментировать строчку:

//Result.MainMenu1 := NewMenu( Result.Form, 0, [ "Test"], nil );

то в отчете MemProof совершенно ничего не меняется. А вот в случае PAS_VERSION меняется: остается только отчет об иконках.


 
Vladimir Kladov   (2006-12-12 18:53) [9]

Меню не наследуется от контрола, оно к нему привязвается. И неважно, к чему вы привязываете меню, раз вы его все равно привязываете, оно убьется автоматически. Всегда есть возможность проверить, остановиться в TMenu.Destroy.


 
AndreyRus   (2006-12-12 20:15) [10]

Испробовал я на досуге TracePlus/Win32 (http://www.sstinc.com) для профилировки программы. IMHO? очень неплохая программа. Многое узнал о своей программе :) В программе все исправил, но остались недоразумения в KOL:

TRUE                   GetVersionExA( 0x004156C4 )
0x00010011             LoadCursorA( 0x00000000,0x00007F00 )
[*]                    GetClassInfoA( 0x00400000,0x00414334,0x0012FEF8 )
[*]                    GetClassInfoA( 0x00400000,0x0012FEB8,0x0012FE60 )
0xC1AD                RegisterClassA( 0x0012FEF8 )
0x002A0510 (obj_Form)  CreateWindowExA(0x10000,"obj_Form","MainForm",0x6CF0000,347,303,CW_USEDEFAULT,CW _USEDEFAULT,0x0,0x0,0x00400000)
*                      CreateMenu()

{...}

[*]   DestroyMenu( 0x00370935 )
*     RemoveMenu(*)
TRUE  DestroyMenu( 0x02270853 )

[*] - Error!!!


Странно как-то создаются оконные элементы. В начале ошибочный запрос - GetClassInfoA, а затем создание и неладное что-то и с уничтожением меню.


 
SergeR ©   (2006-12-13 12:14) [11]

Еще по теме:
Если в на форму "кинуть" какой нибудь компонент из grushcontrols, то память так же не вся освобождается при дестрое, но только тогда, когда у компонента Caption не пустой.
Т.е. если ,например, панельке присвоить caption="something",  то есть утечки.


 
Vladimir Kladov   (2006-12-13 16:38) [12]

GetClassInfo должен спрашиваться, чтобы не пытаться регистрировать по новой такой же класс окна. В VCL вроде так же делается. Меню у меня уничтожается правильно. Сначало оно отсоединяется от окна, потом DestroyMenu. Все эти ресурсосчиталки, и мемпруф в том числе, просто лажаются. Я допускаю, что может быть система успела убить меню до его отсоединения еще до прихода WM_DESTROY, но нигде в документации не говорится, что это так. По крайней мере вызов DestroyXXXX для уже убитого дескриптора никаких неприятностей не даст, и утечек тоже.

Я как-то отправлял исправления по GRushControls недавно (от homm"а), думаю MTsvDN обновил у себя на сайте. Поди, проблемы с ресурсами в неисправленной версии, там не было вызова inherited в деструкторе.


 
AndreyRus   (2006-12-13 19:50) [13]


> GetClassInfo должен спрашиваться, чтобы не пытаться регистрировать
> по новой такой же класс окна.

А откуда он возьмется, если приложение только стартует?


> Все эти ресурсосчиталки, и мемпруф в том числе, просто лажаются.

Равно как и компиляторы, я уж не говорю о людях :)
Лично я никогда не трачу код на освобождение русурсов при закрытии приложения, т.к. это замечательно делает сборщик мусора - OS.


 
Vladimir Kladov   (2006-12-13 20:01) [14]

проблема в том, что мы не знаем, почему вызван деструктор. Заканчивается приложение или просто в коде кто-то объект формы убивает. Делать проверку AppletTerminated смысла нет, потому что это кода только добавит, но никак не убавит.


 
vampir_infernal   (2006-12-14 18:43) [15]

я все таки считаю, что такой простой код проверки освобождения памяти ошибки давать не может:
unit checkMem;
{$WARN SYMBOL_PLATFORM OFF}
interface
implementation
uses sysUtils, kol;

var
  HPs: THeapStatus;
  HPe: THeapStatus;
  lost: integer;

initialization
  HPs := getHeapStatus;

finalization
  HPe := getHeapStatus;
  Lost := HPe.TotalAllocated - HPs.TotalAllocated;
  if lost > 0 then
  begin
     beep;
     ShowMessage(format("lostMem: %d", [lost]));
  end;
end.


 
Vladimir Kladov   (2006-12-14 19:43) [16]

Про косяк в асм-версии TObj.Final я уже писал. В pas_version не должно быть той утечки 44 байта. В выходной будет обновление.

Я про то, что лажаются при подсчете ресурсов-дескрипторов меню, иконок и подобного. Или действительно винда каким-то образом успевает дескриптор меню освободить до его отсоединения, но это противоречит MSDN.



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

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

Наверх




Память: 0.52 MB
Время: 0.028 c
15-1182306120
Slider007
2007-06-20 06:22
2007.07.22
С днем рождения ! 20 июня 2007 среда


2-1182894622
Vlad Oshin
2007-06-27 01:50
2007.07.22
Помогите "переинициализировать" сервис


2-1182861887
Ламер 2.Х
2007-06-26 16:44
2007.07.22
Окна


2-1182836764
sergeyst
2007-06-26 09:46
2007.07.22
Всем привет!


1-1179396051
ancot
2007-05-17 14:00
2007.07.22
winexec