Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
1-1179338084
еррор
2007-05-16 21:54
2007.07.22
Пропадают заголовки столбцов ListView


10-1134471389
Well
2005-12-13 13:56
2007.07.22
Excel. Как управлять автофигурами.


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


2-1182776449
Kolan
2007-06-25 17:00
2007.07.22
ovaerload конструктор &amp;#151; что получится?


1-1175586374
Kolan
2007-04-03 11:46
2007.07.22
Свой ActionList





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский