-
Вот здесь полезная информация: Текущий дамп памяти из 256 байт начиная с адреса 7EF43120: Запускаем программу (F8), в Watches добавляем PDWORD($7EF43120), ставим "Break when changed", и каждый раз, когда первые 4 байта меняются, будет останов. Тут можно посмотреть, кто выделил. Вообще похоже на то, что было добавление в TList, сам TList никто не освободил.
-
Фреймы даже не буду сейчас смотреть, уже просто не помню, что там и как.
Я вообще не вижу проблемы с утечками памяти. Если не мегабайтами течет. В современных приложениях вообще всё течет. Вин-8 - это просто одна сплошная протечка. Проги на шарпах со сборщиками мусора - там вообще не поймешь, то ли они текут беспрерывно, то ли это стратегия такая - мусор собирать раз в сутки.
Вот утечки ресурсов - это серьезно. Можно винду завалить, даже и 7-ку. 8-ку не пробовал (мало я с ней работал), но почему-то есть подозрение, что там ничего не изменилось.
-
> Проги на шарпах
тык если во всех книгах для батонокидателей пишут про наличие сборщика и необязательность высвобождения, то фигли им мучится...
для меня утечка это как минимум сигнал что что то не так, а если что то не так, то в итоге накопится куча неразгребешь вот с меню разобрались, сразу стали видны "скрытые" им другие проблемы
про фреймы хотяб скажи правильно ли им так назначать "родителя" и как их освобождать, просто фри или еще чего надо?
-
> [+] Метод TBitmap.CopyToClipboard переименован в CopyToClipboardAsDIB, > добавлена другая версия CopyToClipboard, использующая формат > CF_BITMAP (существенно более короткий код).
и пока я шарю в клипбордах :) CopyToClipboardAsDIB - вообще нафиг не нужна CF_DIB, CF_DIBV5 и CF_BITMAP взаимно конвертируются самой виндой при запросе конкретного варианта, а в 8ке вся эта метрошная лабуда вообще только CF_BITMAP должна посылать в буфер
-
> правильно ли им так назначать "родителя" и как их освобождать
Я сейчас точно уже не скажу как. В свете сегодняшних рытьёв наверное правильно сказать MyFrame.Form.Close; И да, я знаю, что это не форма, а, в общем-то, панель. Просто отправляется WM_CLOSE, дальше все по свистку от винды.
> CopyToClipboardAsDIB - вообще нафиг не нужна
Пусть останется. Я работал с битмапами, которые бывают только в DIB'е, потому что handle винде выделить не получается, слишком большой. И для совместимости.
-
-
This also contains function format for Freepascal and updated koldef.inc for Freepascal 3.0.1/3.1.1
-
> merged 3.23++
too fast. An error in asm version of run. it should be:
procedure Run( var AppletCtl: PControl );
asm
TEST EAX, EAX
JZ @@exit
PUSH EBX
XCHG EBX, EAX
INC [AppletRunning]
MOV EAX, [EBX]
MOV [Applet], EAX
CALL CallTControlCreateWindow
@@loop: CMP [AppletTerminated], 0
JNZ @@end_loop
CALL WaitMessage
MOV EAX, [EBX]
CALL TControl.ProcessMessages
MOV EAX, [EBX]
CALL [ProcessIdle]
JMP @@loop
@@end_loop:
MOV ECX, [EBX]
XCHG EAX, EBX
POP EBX
JECXZ @@exit
POP EBX
LEA EAX, [Applet]
CMP [EAX], 0
JZ @@exit
CALL TerminateExecution
@@exit:
end;
-
> merged 3.23++
too fast. An error in asm version of run. it should be:
procedure Run( var AppletCtl: PControl );
asm
TEST EAX, EAX
JZ @@exit
PUSH EBX
XCHG EBX, EAX
INC [AppletRunning]
MOV EAX, [EBX]
MOV [Applet], EAX
CALL CallTControlCreateWindow
@@loop: CMP [AppletTerminated], 0
JNZ @@end_loop
CALL WaitMessage
MOV EAX, [EBX]
CALL TControl.ProcessMessages
MOV EAX, [EBX]
CALL [ProcessIdle]
JMP @@loop
@@end_loop:
MOV ECX, [EBX]
XCHG EAX, EBX
POP EBX
JECXZ @@exit
POP EBX
LEA EAX, [Applet]
CMP [EAX], 0
JZ @@exit
CALL TerminateExecution
@@exit:
end;
-
> Но исправление слишком радикальное, меняется порядок уничтожения > окон. Может вылезти что угодно. Поэтому все можно будет > вернуть по заклинанию LET_MENU_LEAK.
в общем печаль-тоска подобралась незаметно, есть новый виновник утечек и вылетов ---- KOLApplet обнаружил при попытке разборок с фреймами, мысль была что может без него им плохо живется, ну типа по аналогии с несколькими формами ток положил на форму и хобана + еще 8 утечек
потом 1)беру болванку эксперимента с меню, что выкладывал здесь, для приличия добавил 2ю форму, без апплета, запустил\закрыл - чисто 2) кладу аплет, запустил\закрыл - стоп в CPU-окне отладчика на user32.DestroyWindow 3) думаю, предупреждал же... 4) ставлю дефин LET_MENU_LEAK, удалил меню, для чистоты эксперимента, запустил\закрыл - 9 утечек, включая те самые Тлисты.... 5) убираю аплетт, , запустил\закрыл - портянка на весь экран ошибка памяти 6) убираю дефин LET_MENU_LEAK, запустил\закрыл - чисто
кино ннада?
-
> Но исправление слишком радикальное, меняется порядок уничтожения > окон. Может вылезти что угодно. Поэтому все можно будет > вернуть по заклинанию LET_MENU_LEAK.
в общем печаль-тоска подобралась незаметно, есть новый виновник утечек и вылетов ---- KOLApplet обнаружил при попытке разборок с фреймами, мысль была что может без него им плохо живется, ну типа по аналогии с несколькими формами ток положил на форму и хобана + еще 8 утечек
потом 1)беру болванку эксперимента с меню, что выкладывал здесь, для приличия добавил 2ю форму, без апплета, запустил\закрыл - чисто 2) кладу аплет, запустил\закрыл - стоп в CPU-окне отладчика на user32.DestroyWindow 3) думаю, предупреждал же... 4) ставлю дефин LET_MENU_LEAK, удалил меню, для чистоты эксперимента, запустил\закрыл - 9 утечек, включая те самые Тлисты.... 5) убираю аплетт, , запустил\закрыл - портянка на весь экран ошибка памяти 6) убираю дефин LET_MENU_LEAK, запустил\закрыл - чисто
кино ннада?
-
> беру болванку эксперимента с меню
с дефином PAS_VERSION, чудеса не менее интересные, включая "рунтаймеррор"
-
> беру болванку эксперимента с меню
с дефином PAS_VERSION, чудеса не менее интересные, включая "рунтаймеррор"
-
Package is now updated as per Vladimir's change. (kol_asm.inc)
-
Package is now updated as per Vladimir's change. (kol_asm.inc)
-
Вот где ошибка: procedure TerminateExecution( var AppletCtl: PControl ); var App: PControl; Appalreadyterminated: Boolean; begin Appalreadyterminated := AppletTerminated; AppletTerminated := TRUE; AppletRunning := FALSE; App := Applet; Applet := nil; if (App <> nil) {and (App.RefCount >= 0)} then begin {$IFDEF LET_MENU_LEAK} //was IFNDEF !!! App.RefInc; {$ENDIF} if not Appalreadyterminated then begin App.ProcessMessages; App.Perform( WM_CLOSE, 0, 0 ); end; AppletCtl := nil; {$IFNDEF LET_MENU_LEAK} // версия KOL 3.23+: DestroyWindow(App.Handle); //** В этом варианте вызывается не деструктор {$ELSE} // объекта, а функция закрытия окна. Вызов App.Free; App.RefDec; // деструктора выполнится в обработчике {$ENDIF} // события WM_DESTROY. В результате, сначала end; // успешно разрушится меню формы. 22.02.2015 end;
и вот тут, соответственно (kol_asm.inc, + перенос кода за скобки ifdef'а, так что лучше всю процедуру заменить): procedure TerminateExecution( var AppletCtl: PControl );
asm
PUSH EBX
PUSH ESI
MOV BX, $0100
XCHG BX, word ptr [AppletRunning]
XOR ECX, ECX
XCHG ECX, [Applet]
JECXZ @@exit
PUSH EAX
XCHG EAX, ECX
MOV ESI, EAX
CALL TObj.RefInc
TEST BH, BH
JNZ @@closed
MOV EAX, ESI
CALL TControl.ProcessMessages
PUSH 0
PUSH 0
PUSH WM_CLOSE
PUSH ESI
CALL TControl.Perform
@@closed:
POP EAX
XOR ECX, ECX
MOV dword ptr [EAX], ECX
MOV EAX, ESI
CALL TObj.RefDec
XCHG EAX, ESI
CALL TObj.RefDec
PUSH [ESI].TControl.FHandle
CALL Windows.DestroyWindow
@@exit:
POP ESI
POP EBX
end;
-
Вот где ошибка: procedure TerminateExecution( var AppletCtl: PControl ); var App: PControl; Appalreadyterminated: Boolean; begin Appalreadyterminated := AppletTerminated; AppletTerminated := TRUE; AppletRunning := FALSE; App := Applet; Applet := nil; if (App <> nil) {and (App.RefCount >= 0)} then begin {$IFDEF LET_MENU_LEAK} //was IFNDEF !!! App.RefInc; {$ENDIF} if not Appalreadyterminated then begin App.ProcessMessages; App.Perform( WM_CLOSE, 0, 0 ); end; AppletCtl := nil; {$IFNDEF LET_MENU_LEAK} // версия KOL 3.23+: DestroyWindow(App.Handle); //** В этом варианте вызывается не деструктор {$ELSE} // объекта, а функция закрытия окна. Вызов App.Free; App.RefDec; // деструктора выполнится в обработчике {$ENDIF} // события WM_DESTROY. В результате, сначала end; // успешно разрушится меню формы. 22.02.2015 end;
и вот тут, соответственно (kol_asm.inc, + перенос кода за скобки ifdef'а, так что лучше всю процедуру заменить): procedure TerminateExecution( var AppletCtl: PControl );
asm
PUSH EBX
PUSH ESI
MOV BX, $0100
XCHG BX, word ptr [AppletRunning]
XOR ECX, ECX
XCHG ECX, [Applet]
JECXZ @@exit
PUSH EAX
XCHG EAX, ECX
MOV ESI, EAX
CALL TObj.RefInc
TEST BH, BH
JNZ @@closed
MOV EAX, ESI
CALL TControl.ProcessMessages
PUSH 0
PUSH 0
PUSH WM_CLOSE
PUSH ESI
CALL TControl.Perform
@@closed:
POP EAX
XOR ECX, ECX
MOV dword ptr [EAX], ECX
MOV EAX, ESI
CALL TObj.RefDec
XCHG EAX, ESI
CALL TObj.RefDec
PUSH [ESI].TControl.FHandle
CALL Windows.DestroyWindow
@@exit:
POP ESI
POP EBX
end;
-
> Package is now updated as per Vladimir's change. (kol_asm. > inc)
Thaddy, you are still too fast! :)
-
> Package is now updated as per Vladimir's change. (kol_asm. > inc)
Thaddy, you are still too fast! :)
-
> Vladimir Kladov © (24.02.15 13:08) [31]
да-да по крайней мере паскальный вариант, самый большой проект, где был Tlist в логе - это и было изза апплета, сейчас все чисто
остался только косяк с фреймами (или табами) в другом
> Запускаем программу (F8), в Watches добавляем PDWORD($7EF43120), > ставим "Break when changed", и каждый раз, когда первые > 4 байта меняются, будет останов. Тут можно посмотреть, кто > выделил.
чет в 7ке нет такого "Break when changed" и пролетает мимо ненаходит
|