Форум: "KOL";
Текущий архив: 2007.07.22;
Скачать: [xml.tar.bz2];
ВнизНе правильное освобождение 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 вся ветка
Форум: "KOL";
Текущий архив: 2007.07.22;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 3.267 c