-
[-] Исправления в KOL: WStrRScan - код скопирован из StrRScan. Исходная версия WStrRScan работала некорректно в случае отсутствия искомого образца.
[-] Исправления в обработчике WM_NCDESTROY для корректного уничтожения меню (не мог быть разрушен после разрушения окна-владельца).
[*] Улучшена функция ClipboardHasText - удален ненужный код.
[+] Метод TBitmap.CopyToClipboard переименован в CopyToClipboardAsDIB, добавлена другая версия CopyToClipboard, использующая формат CF_BITMAP (существенно более короткий код).
-
> для корректного уничтожения меню
и какие такие дефины в проекте должны стоять, чтоб до этого исправления дошёл код вообще????
при закрытии в тестовом приложении как были утечки меню из под дельфи, так и остались, а в крупном проекте еще и ошибки памяти вылезли, попытка модификации после освобождения
-
-
> чтоб до этого исправления дошё
Да, я забыл про kol_asm.inc. Перевыложил, заодно и в kol.pas пару исправлений внес. В частности, добавил, что по заклинанию LET_MENU_LEAK все будет как раньше. Еще раз проверил в MemProof 0.9.4.8 и с FastMM3. Все чисто. > какая связь между этими адресами?http://sourceforge.net/projects/kolmck/http: > //sourceforge.net/projects/keyobjectslibrary/
Один из них не мой.
-
> Один из них не мой.
не ну я так-то догадался, просто они тож чето там улучшают вы типа не скооперированы вообще?
-
> Да, я забыл про kol_asm.inc. Перевыложил, заодно и в kol. > pas пару исправлений внес. В частности, добавил, что по > заклинанию LET_MENU_LEAK все будет как раньше. Еще раз проверил > в MemProof 0.9.4.8 и с FastMM3. Все чисто.
не, не работает вот проверь тут полный комплект https://yadi.sk/d/1JxuHV9kedCXf запускай из под среды
-
если это - это, то это копец, такая куча дефинов что до Final вообще недоходит
WM_NCDESTROY: {$IFnDEF SMALLER_CODE} if fHandle = Msg.hwnd then {$ENDIF} begin {$IFNDEF LET_MENU_LEAK} if IsForm then begin {$IFNDEF SMALLER_CODE} Hide; // VK: to destroy form visually faster, 18.02.2015 {$ENDIF} {$IFNDEF SMALLEST_CODE} Final; // VK: to provide correct menu destroying, 18.02.2015 {$ENDIF} end; {$ENDIF} {$IFnDEF SMALLER_CODE} {$IFDEF USE_PROP} RemoveProp( fHandle, ID_SELF ); //********* Added By M.Gerasimov {$ELSE} SetWindowLong( fHandle, GWL_USERDATA, 0 ); // VK + Alexey Kirov, 23.02.2012 {$ENDIF} {$ENDIF} //------------------------------------------- Default; Exit; end;
с PAS_VERSION вообще ниодна строчка в function TControl.WndProc( var Msg: TMsg ): Integer; неактивна в KOL.Pas
-
Вообще-то, все доходит. Это у Вас что-то неправильно. Например, не та версия исходников компилируется.
Мои исправления вообще не касались утечек памяти. FastMM3 их не показывал. Я решал проблему утечки ресурса меню. Пытался решить. Сейчас выкладываю новое исправление. На этот раз удалось лучше. И заодно проблемы с FastMM4 устраняются. Но исправление слишком радикальное, меняется порядок уничтожения окон. Может вылезти что угодно. Поэтому все можно будет вернуть по заклинанию LET_MENU_LEAK.
Уже выложил.
-
ну во первых в комплекте отсутствует koladd.pas хотя требуется для установки
-
во вторых чую придется снимать кино....
-
-
Сразу: FastMM я скачал сам, версия 4.991, ваша 4.97. Вряд ли много отличий, но лучше, если Вы обновитесь. Дальше: я использовал Delphi7 под XP SP3 (виртуалка) со всеми обновлениями. delphi5 я давно не использую, но даже если с ней работать, для нее есть обновления. Слово нулевая нехорошо звучит.
Далее, для проверки с FastMM он должен быть первым в проекте. Рекомендую проверять это перед каждым билдом. MCK любит ссылку на KOL ставить на первое место.
Кроме того, для лучшей диагностики надо править опции проекта, убирать оптимизацию, добавлять в линкере символы TD32, тогда диагностика показывает красивше. Если до нее доходит дело, конечно.
-
> нулевая нехорошо звучит
это звучит как "с обновой, без экспертов, без компонентов, с дефолтными настройками" XP SP3 (виртуалка) со всеми обновлениями - тоже самое рабочий Delphi7 + полуживая Win7x64 - тот же результат кудаб не писал FastMM, даже в сам кол.пас - никакой разницы хоть с какими настройками отладки версию FastMM попробую канешн обновить, но веть логично, что если например в 2.79 такого не происходит, то проблема не в FastMM?
-
Да, не в нем. Потому что я уже попробовал и с вашей версией FastMM, и с Delphi5 уже (и даже без обновлений). И у меня все чисто. Еще подумал, может, FastMM молча падает. Нет, останавливается на строке кода FinalizeMemoryManager, по F8, выполняет и хочет работать дальше. Ни сообщений, ни логов. Добавляю опцию LET_MENU_LEAK, сообщения про утечки есть.
Проверьте, что с сайта KOL скачалась именно версия 3.23 (в начале kol.pas VERSION 3.23+). MCK я не менял с июня.
Если не компилятор (версия Delphi), остается только железо и ОС, а это очень странно.
-
вобщем с "новым" фастмм и всеми дебугами без оптимизаций без LET_MENU_LEAK без среде в винде также ошибка с LET_MENU_LEAK в винде без ошибки, а в среде вот такой вот файл с номерами строк, все по ГОСТу https://yadi.sk/i/znRAQNpxepuP4
-
Обновил только что, 3.23++. Удалось получить сообщения под win7. Не знаю, виртуалка виновата, или еще что, но под XP оно как-то не детектило.
-
если DEP включен для всех прог и делфи с проектным файлом не внесено в исключения, тогда может проглатывать
-
так так так... с меню вроде норм стало, по крайней мере, тестовый примитив и прога средней сложности молчит однако в навороченной есть косяк. но уже не с меню, а похоже на Tlist, тоже из под делфи
-
-
о еще косяк в другой поделке если я впихиваю формы-фрэймы в таб контрол вот так (может это через Ж..) NewForm2(Form2,TabControl1.Pages[2]); NewForm3(Form3,TabControl1.Pages[1]);
то из под делфи опятьже утечка по этим 2м вкладкам или фрэмам, когда табконтроле были панели такого не было https://yadi.sk/i/2iRkCf-NeqC5Pс какой версии эти глюки не скажу, ибо они прятались среди громадья глюков меню
-
Вот здесь полезная информация: Текущий дамп памяти из 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" и пролетает мимо ненаходит
-
> Vladimir Kladov © (24.02.15 13:08) [31]
да-да по крайней мере паскальный вариант, самый большой проект, где был Tlist в логе - это и было изза апплета, сейчас все чисто
остался только косяк с фреймами (или табами) в другом
> Запускаем программу (F8), в Watches добавляем PDWORD($7EF43120), > ставим "Break when changed", и каждый раз, когда первые > 4 байта меняются, будет останов. Тут можно посмотреть, кто > выделил.
чет в 7ке нет такого "Break when changed" и пролетает мимо ненаходит
-
PDWORD(адрес)^ - разыменовать надо.
-
PDWORD(адрес)^ - разыменовать надо.
-
Обновил KOL.zip на kolmck.net.
-
Обновил KOL.zip на kolmck.net.
-
табконтрол вроде не причём, на панелях также фастмм указывает на создание фрейма в файлах типа Unit2_1.inc
procedure NewForm2( var Result: PForm2; AParent: PControl ); begin
{$IFDEF KOLCLASSES} Result := PForm2.Create; {$ELSE OBJECTS} New( Result, Create );<<<<<<<<<<<<<<<<<<<<<<<<<< {$ENDIF KOL CLASSES/OBJECTS} Result.Form := NewPanel( AParent, esNone ).MarkPanelAsForm; Result.Form.DF.FormAddress := @ Result.Form; Result.Form.DF.FormObj := Result; Result.Form.SetClientSize( 468, 278 ); Result.EditBox1 := NewEditBox( Result.Form, [ ] ).SetPosition( 168, 104 ); Result.EditBox1.Text := 'EditBox1'; Result.EditBox1.Color := TColor(clWindow); Result.Form.CreateWindow;
end; показано <<<<<<<<<<<<< хоть free, хоть close - одинаково
-
табконтрол вроде не причём, на панелях также фастмм указывает на создание фрейма в файлах типа Unit2_1.inc
procedure NewForm2( var Result: PForm2; AParent: PControl ); begin
{$IFDEF KOLCLASSES} Result := PForm2.Create; {$ELSE OBJECTS} New( Result, Create );<<<<<<<<<<<<<<<<<<<<<<<<<< {$ENDIF KOL CLASSES/OBJECTS} Result.Form := NewPanel( AParent, esNone ).MarkPanelAsForm; Result.Form.DF.FormAddress := @ Result.Form; Result.Form.DF.FormObj := Result; Result.Form.SetClientSize( 468, 278 ); Result.EditBox1 := NewEditBox( Result.Form, [ ] ).SetPosition( 168, 104 ); Result.EditBox1.Text := 'EditBox1'; Result.EditBox1.Color := TColor(clWindow); Result.Form.CreateWindow;
end; показано <<<<<<<<<<<<< хоть free, хоть close - одинаково
-
KOL_asm.inc: 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;
-
KOL_asm.inc: 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;
-
В destructor TMenu.Destroy не используется (но определяется) Next.
-
В destructor TMenu.Destroy не используется (но определяется) Next.
-
> CMP [EAX], 0 <-ОШИБКА!!!!
Какая? В Delphi7 ошибки нет. У вас что, Free Pascal? Delphi 201x? Пишите яснее. > В destructor TMenu.Destroy не используется (но определяется) > Next.
destructor TMenu.Destroy;
var Next, Prnt: PMenu;
Save_Ref: Integer;
begin
LogFileOutput( GetStartDir + 'TMenu.Destroy.txt',
Int2Hex( DWORD( @ Self ), 6 ) + ' ' + Int2Str( RefCount ) );
if Count > 0 then
begin
FMenuItems.ReleaseObjects;
FMenuItems := NewList;
end;
if FParentMenu <> nil then
begin
Save_Ref := Self.fRefCount; Self.fRefCount := 17;
Prnt := FParentMenu;
Next := Prnt.RemoveSubMenu( FId );
FParentMenu := nil;
Prnt.FMenuItems.Remove( @ Self );
Self.fRefCount := Save_Ref;
if Next = nil then Exit;
end;
if (FControl <> nil) and (FControl.fMenu = FHandle) and (FHandle <> 0) then
begin
if not (G2_Destroying in FControl.fFlagsG2)
not FControl.fDestroying then begin
Windows.SetMenu( FControl.fHandle, 0 );
end;
FControl.fMenu := 0;
Next := PMenu( FControl.fMenuObj );
while Next <> nil do
begin
if Next.fNextMenu = @Self then
begin
Next.fNextMenu := fNextMenu;
break;
end;
Next := Next.fNextMenu;
end;
end;
Next := fNextMenu;
if FBitmap <> 0 then
Bitmap := 0;
if FHandle <> 0 then
begin
DestroyMenu( FHandle )
;
end;
FCaption := '';
FMenuItems.Free;
Next.Free;
inherited;
end; Расскажите уже, каким компилятором пользуетесь, что он такую чушь сказал.
-
> CMP [EAX], 0 <-ОШИБКА!!!!
Какая? В Delphi7 ошибки нет. У вас что, Free Pascal? Delphi 201x? Пишите яснее. > В destructor TMenu.Destroy не используется (но определяется) > Next.
destructor TMenu.Destroy;
var Next, Prnt: PMenu;
Save_Ref: Integer;
begin
LogFileOutput( GetStartDir + 'TMenu.Destroy.txt',
Int2Hex( DWORD( @ Self ), 6 ) + ' ' + Int2Str( RefCount ) );
if Count > 0 then
begin
FMenuItems.ReleaseObjects;
FMenuItems := NewList;
end;
if FParentMenu <> nil then
begin
Save_Ref := Self.fRefCount; Self.fRefCount := 17;
Prnt := FParentMenu;
Next := Prnt.RemoveSubMenu( FId );
FParentMenu := nil;
Prnt.FMenuItems.Remove( @ Self );
Self.fRefCount := Save_Ref;
if Next = nil then Exit;
end;
if (FControl <> nil) and (FControl.fMenu = FHandle) and (FHandle <> 0) then
begin
if not (G2_Destroying in FControl.fFlagsG2)
not FControl.fDestroying then begin
Windows.SetMenu( FControl.fHandle, 0 );
end;
FControl.fMenu := 0;
Next := PMenu( FControl.fMenuObj );
while Next <> nil do
begin
if Next.fNextMenu = @Self then
begin
Next.fNextMenu := fNextMenu;
break;
end;
Next := Next.fNextMenu;
end;
end;
Next := fNextMenu;
if FBitmap <> 0 then
Bitmap := 0;
if FHandle <> 0 then
begin
DestroyMenu( FHandle )
;
end;
FCaption := '';
FMenuItems.Free;
Next.Free;
inherited;
end; Расскажите уже, каким компилятором пользуетесь, что он такую чушь сказал.
-
Во вчерашнем обновлении не довставил новый TerminateExecution в KOL_ASM.INC. Поправить смогу только вечером. Берите код, что я здесь привел вчера, и вставьте сами (отличается комментариями с паскаль-кодом). Либо включите PAS_VERSION.
-
Во вчерашнем обновлении не довставил новый TerminateExecution в KOL_ASM.INC. Поправить смогу только вечером. Берите код, что я здесь привел вчера, и вставьте сами (отличается комментариями с паскаль-кодом). Либо включите PAS_VERSION.
-
Я в курсе. Начиная с Windows 8.1, GetVersion/GetVersionEx объявлена устаревшей. Для того, чтобы приложение правильно определяло версию, к нему нужен специально оформленный манифест.
-
Короткий вариант, определяет до 10 версии (9х поддержки нет):
function WinVerShort: TWindowsVersion;
begin
case LoWord(GetVersion) of
$0005: Result := wvY2K;
$0105: Result := wvXP;
$0205: Result := wvServer2003;
$0006: Result := wvVista;
$0106: Result := wvSeven;
$0206: Result := wvEight;
$0306: Result := wvEight_1;
$000A: Result := wvTen;
else
Result := wvNT;
end;
end;
Нужен подобный манифест:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity
type="win32"
name="DelphiApplication"
version="1.0.0.0"
processorArchitecture="*"
/>
<description> my foo exe </description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="asInvoker"
uiAccess="false"
/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id=""/>
<!-- Windows 8.1 -->
<supportedOS Id=""/>
<!-- Windows Vista -->
<supportedOS Id=""/>
<!-- Windows 7 -->
<supportedOS Id=""/>
<!-- Windows 8 -->
<supportedOS Id=""/>
</application>
</compatibility>
</assembly>
-
актуальный манифест нынче очень полезен.
функция _WStrLComp в паскалевском исполнении за гранью добра и зла из за неё не работают Name Value в WStrList, например
-
p.s. Ну не то что бы за гранью, но может запилить SVN комюнити? Образовалось ещё одно применение для KOL: firemonkey программы для Windows. Всякие Tray Icon, tree и прочее
-
При создании приложения в KOLProject меняем шрифт - в проекте в файле .inc меняются параметры любые, кроме имени шрифта. В итоге шрифт ВСЕГДА System независимо от заданного. Эта шляпа тянется уже давно - то работает, то после очередного обновления КОЛ опять не работает.
-
Form.Font.ReleaseHandle;
Form.Font.AssignHandle(GetStockObject(DEFAULT_GUI_FONT));
But I also have a better, but more complicated solution.
-
Ошибка в PAS_ONLY версии функции StrScan - функция никогда не возвращает nil, что приводит к ошибке, если символ не найден. Правильный код:
function StrScan(Str: PAnsiChar; Chr: AnsiChar): PAnsiChar;
begin
Result := nil;
if Str = nil then Exit;
while Str^ <> #0 do
begin
if Str^ = Chr then
begin
Result := Str;
Break;
end;
Inc(Str);
end;
end;
-
А если StrScan исправить, то другие функции начнут глючить... Во многих местах не проверки на nil
ps. вроде как то обсуждалось уже, надо поискать..
-
> А если StrScan исправить, то другие функции начнут глючить.
Нет, в том то и смысл, что из описания этой функции следует, что она должна вернуть nil, если символ не найден. Соответственно, весь код и так проверяет возвращаемый результат. И в случае PAS_ONLY успешно падает при ненахождении символа. Когда-то в старых версиях этот же баг был и в ASM-версии, но его исправили, а в PAS - забыли.
> вроде как то обсуждалось уже, надо поискать
Сравнительно недавно то же обсуждали и правили в WStrScan. Так сказать, по образу и подобию...
-
Напомню. Оригинал выглядит так: function StrScan(Str: PAnsiChar; Chr: AnsiChar): PAnsiChar;
begin
while Str^ <> Chr do
begin
if Str^ = #0 then break;
inc(Str);
end;
Result := Str;
end; В случае ненахождения символа возвращается не nil, а указатель на терминирующий #0. Ну, и без проверки if Str = nil then Exit сама функция StrScan не падает только потому, что при вызове её обычно как if StrScan(PChar(S), 'A') <> nil then, Delphi при приведении строки к PChar вставляет ещё один вызов функции, которая проверяет строку на пустоту и для пустой строки возвращает действительный указатель на заранее заготовленный символ #0, лежащий где-то в области констант или глобальных переменных. Так вот, если захочется ускориться, чтобы Delphi не вызывал дополнительную функцию, и вызвать StrScan как if StrScan(Pointer(S), 'A') <> nil then, то без проверки параметра Str на nil функция упадёт. Я только что глянул, WStrScan тоже надо поправлять.
-
> Нет, в том то и смысл, что из описания этой функции следует, > что она должна вернуть nil, если символ не найден.
Например функция StrScan, проверок нету.
> function StrScan(Str: PAnsiChar; Chr: AnsiChar): PAnsiChar; .....
Изменения на svn внёс, StrScan пофиксил заодно.
WStrScan и ASM версии - не смотрел...
-
> Например функция StrScan, проверок нету.
Имелась ввиду функция StrCat, копи-паста она такая)
-
А-а-а, там ещё и StrCat есть. А может кто-то на пальцах объяснить логику этой функции? Как я понимаю, эта функция объединяет две строки в одну, результат заносит по указателю в Dest, в качестве результата возвращает указатель на Dest. Типа, так?
procedure Test; var Src, Dst: string; begin Dst := 'ABC'; Src := 'DEF'; MessageBox(0, StrCat(PAnsiChar(Dst), PAnsiChar(Src)), '', 0); // PS: Этот код выдаёт ошибку! end;
Вопрос: а кто ж в этой фунции занимается выделением памяти под результат объединения, а затем должен освободить эту память? Чтоб далеко не ходили, приведу оригиналы этих функций:
function StrScan(Str: PAnsiChar; Chr: AnsiChar): PAnsiChar; begin while Str^ <> Chr do begin if Str^ = #0 then break; inc(Str); end; Result := Str; end;
function StrCopy( Dest, Source: PAnsiChar ): PAnsiChar; var L: Integer; begin L := StrLen(Source); Move(Source^, Dest^, L+1); Result := Dest; end;
function StrCat( Dest, Source: PAnsiChar ): PAnsiChar; begin // Итак. Оригинальная StrScan найдёт #0 в конце Dest // и вернёт нам указатель на конец Dest // Функция StrCopy должна скопировать Source в конец Dest // Спрашивается: а кто должен дать гарантию, что после // оригинального Dest есть свободное место, откуда оно взялось, // и кто отвечает за его освобождение? StrCopy( StrScan( Dest, #0 ), Source ); Result := Dest; end;
Исходя из выше озвученных рассуждений правильное использование должно выглядеть так:
procedure Test; var Src, Dst: string; begin Dst := 'ABC'; Src := 'DEF'; SetLength(Dst, Length(Dst)+Length(Src)); // Выделили память в Dst, чтобы уместить Dst+Src MessageBox(0, StrCat(PAnsiChar(Dst), PAnsiChar(Src)), '', 0); end;
Где в цепочке вызовов StrCat->StrCopy+StrLen->StrScan находится термин "fast" из описания функции StrCat (в отличие от обычного Dst := Dst + Src;)?
Нюанс: в моей поправке StrScan символ #0 не найдётся. Потому что этот символ - это ограничитель null-terminated строки (используемой с типом PChar). Он не может являться частью строки (в отличие от дельфийского string). Единственная необходимость в получении указателя на #0 - это определение конца строки. И зачем это необходимо? Для определения количества символов, расположенных по указателю PChar (до терминирующего #0), используется функция StrLen().
-
> Нюанс: в моей поправке StrScan символ #0 не найдётся.
Ну вот, как и говорил, исправили одно - сломали другое...
> Единственная необходимость в получении указателя на #0 - > это определение конца строки. И зачем это необходимо? Для > определения количества символов, расположенных по указателю > PChar (до терминирующего #0), используется функция StrLen(). >
В StrCat же и используется.
> Где в цепочке вызовов StrCat->StrCopy+StrLen->StrScan находится > термин "fast" из описания функции StrCat (в отличие от обычного > Dst := Dst + Src;)?
Не совсем понимаю, а зачем здесь термин fast?
> // Спрашивается: а кто должен дать гарантию, что после > // оригинального Dest есть свободное место, откуда оно > взялось, > // и кто отвечает за его освобождение?
Гарантий никто не дает. Просто бывает с PChar строками так работают. Выделяют память с запасом, а потом через StrCat клеят.
-
> исправили одно - сломали другое...
Описание StrScan(): {* Fast search of given character in a string. Pointer to found character (or nil) is returned. }
То-есть, должна вернуть nil, если искомый символ не найден. А условием ненахождения искомого символа является достижение символа #0. Тогда для поиска #0 нужно добавлять ещё условие. Например, так:
function StrScan(Str: PAnsiChar; Chr: AnsiChar): PAnsiChar; begin Result := nil; if Str = nil then Exit; while Str^ <> #0 do begin if Str^ = Chr then begin Result := Str; Exit; end; Inc(Str); end; if (Chr = #0) and (Str^ = #0) then Result := Str; end;
> а зачем здесь термин fast?
Я ни при чем. Описание функции StrCat: {* Append source string to destination (fast). Pointer to Dest is returned. }
> Выделяют память с запасом, а потом через StrCat клеят.
Я бы использовал Move() и не заморачивался (тем более, что вызывающему обычно точно известно, сколько места уже занято в том участке памяти, и сколько его выделено, следовательно, лишние StrLen ему не нужны).
Сделайте эту StrCat так:
function StrCat(Dest, Source: PAnsiChar): PAnsiChar; begin Result := Dest; if (Dest = nil) or (Source = nil) then Exit; Move(Source^, Dest[StrLen(Dest)], StrLen(Source)+1); end;
-
PS: условие and (Str^ = #0) в вышеприведенному коде StrScan, наверное, можно выбросить.
-
>> Сделайте эту StrCat так: Вкорне неверно. У вас не выделена память для строки Dest, чтобы принять Source простым копированием данных. Для начала нужно выделить память, а уж после копировать.
-
Я чет ваще не тащу - зачем так сделано? function StrCopy( Dest, Source: PAnsiChar ): PAnsiChar;
var L: Integer;
begin
L := StrLen(Source);
Move(Source^, Dest^, L+1);
Result := Dest;
end; Это ж бред. К примеру, есть у нас две строки "AAA" и "BBB". Мы передаем указатели в StrCopy и что получается? "BBB" копируется после "AAA" и получится "AAABBB". Но! Память для строки "AAA" у нас выделена только на три(!!) символа! А мы тупо копируем в область после первой строки (которая по идее ей еще не принадлежит) вторую строку. Это все равно что пытаться копировать один массив, выделенный GetMem, в конец второго массива. Но память-то выделена только под каждый размер массивов раздельно! Для слияния массивов нам надо Realloc памяти первого массива, с размером суммарных размеров массивов.
-
И еще. Move(Source^, Dest^, L+1) скопирует содержимое Source в НАЧАЛО Dest!!! Разве это верно?
-
Тьфу, я все напутал - думаю про StrCat, а пишу про StrCopy...
StrCopy должна сначала сделать длину Dest равной длине Source, а потом копировать. Ведь размеры строк могут различаться.
А вот в [72] все сказанное верно для StrCat в [69].
-
> StrCopy должна сначала сделать длину Dest равной длине Source
Ну, мы выше выяснили, что для этих функций вызывающий сам должен беспокоиться куда будут помещаться новые данные. Либо вообще не пользоваться этими функциями. Но то, что они должны как минимум работать согласно их описанию, - обязательно. > скопирует содержимое Source в НАЧАЛО Dest
Это так и задумано - вызывающий сам передаёт указатель, по которому нужно записать данные. А указывать этот указатель может куда угодно. Например, StrCat находит указатель на завершающий #0 и передаёт его в эту функцию. Напоминаю: если вы пользуетесь типом string, то вместо StrCat лучше использовать Dst := Dst + Src, а если таких операций много (типа, for i := 1 to 100000 do S := S + S2;) то такой код заменяется на такой: L := Length(S2);
if L = 0 then Exit;
SetLength(S, 100000 * L);
i := 1;
while i <= 100000 do
begin
Move(S2[1], S[i], L);
Inc(i, L);
end;
-
>> для этих функций вызывающий сам должен беспокоиться куда будут помещаться новые данные Не соглашусь. Я, к примеру, этими функциями не пользовался и если бы стал - даже не подумал бы, что я сам должен чего-то увеличивать, прежде чем вызывать. Это все должно делаться внутри функции, а не до ее вызова.
-
Так и я тоже не подозревал о существовании этих функций. Просто пришлось делать выводы, глядя на их код.
-
Еще один момент. Интенсивное использование Stream (проверял на открытом большом файле и из него копировал подряд куски в другие файлы - порядка 1000+ файлов) роняет приложение. Сначала все идет норм, потом АВ. То же самое на стандартном дельфевом TFileStream без проблем и падений.
-
Dimaxx, а как то отладчиком реально поймать? или тулзами типа madExcept?
-
Dimaxx, ты бы выложил минимальную процедурку, которая делает что надо. Может быть, где-то с указателями на буфер и размером данных напутал.
-
>> а как то отладчиком реально поймать? или тулзами типа madExcept? По идее при АВ выдается адрес исключения. Надо по нему прыгнуть в код и увидеть где произошло исключение. >> ты бы выложил минимальную процедурку, которая делает что надо. Может быть, где-то с указателями на буфер и размером данных напутал. Я ж говорю - дельфевый выполняет ту же операцию без проблем. Размеры файлов все известны - они в виде списка типа "имя-размер": SomeDir/SomeFile.dat 12345 Сами файлы все слиты один за одним в один огромный файл без заголовков. По сути различия только в коде со Stream. В выходные постараюсь найти код и опробовать, я уже не помню что и как делал.
-
Насчёт Stream. Адаптировал на КОЛ библиотеки NewAC и LZMA2 - может конечно я чёто неправильно делаю - смысл такой -
type PA=^TA; TA=object(TObj) ... FStream:PStream; ... // etc end;
Ну и соответственно процедуры типа ReadLZMA(...) SeekLZMA(...) etc в соответствующей структуре.
ДАК ВОТ - пишу прогу с использованием оригинальных классов LZMA и соответственно с моим объектом. Разница - 160К. НО!!! прога с классами быстрее раз в 5. всё делал вроде бы по закону. Такое же наблюдается с адаптационными объектами NewAC (при чтении и распаковке файлов, но там возможно ДЛЛ гонит... но в классах же не гонит... хз), и не только. Некоторые адаптации с сайта (DlUCL напр.) тоже тормозят в сравнении с классом.
Делал тестовый класс/объект с рандомным потоком - вроде всё норм... хз...
-
Не представляю что там может тормозить. Сколько там того объекта? Может где-то в часто вызываемые процедуры объект передаётся не по ссылке, а по значению? Всё равно, разница в скорости вряд-ли была бы больше 20%, хотя зависит от кода...
-
Вопрос по падение снимается. Нашел старый проект, скомпилировал - 2 гиговый файл "разложился" без проблем.
-
to:Netspirit Вот и я не могу понять. Оригинальный класс наследуется от TFileStream. Я же делаю объект от KOL.TObj, делаю поле Stream:PStream; делаю в конструкторе NewStream(ProcRec), где ProcRec - record ReadProc, WriteProc, SeekProc etc. end; соответственно перевожу методы из оригинального класса в функции Read,Write,Seek итд. Короче вроде всё правильно. О том что "вызываемые процедуры объект передаётся не по ссылке, а по значению" - не, я уже забыл когда на ВЦЛ писАл. Да и компилятор не позволит. ХЗ чё за фигня... Могу выложить модуль на справедливый народный суд. Модуль сколько весит - не помню, не от себя сейчас сижу. Чё-то около 2000-2500 строк.
-
Шрифт в КОЛ уже реально выбешивает. Задаешь шрифт (Tahoma, height=-11, он по умолчанию), в дизайнере все нормально. Компиляция, запуск. Какого хрена??? Шрифт, мать его, System (корявый растровый .fon), размер, мать его, 10. В unit1_1.inc про шрифт вообще ни строчки. Ничего не меняется, даже если в коде руками поставить имя шрифта (Tahoma) и высоту (-11). Ставишь -12 - шрифт Tahoma, высота -12 - все верно, но мне надо стандартный. Любое FontQuality не меняет ничего. Выставляешь fqProof - в unit1_1.inc ко всем контролам формы прописывается высота шрифта, но не та, что я задал (-11), а -13. Опять-таки WTF?? В итоге шрифт все же становится Tahoma, но размер неверный. И после возвращения FontQuality=fqDefault ничего не меняется, потому что весь unit1_1.inc испещрен FontHeight:=-13. Убрал руками все. Скомпилировал - шрифт опять System. То есть КОЛ игнорирует заданное и пихает свое. DefFont в KOL.pas установлен точно также - Tahoma, -11. Пишу руками в unit1_1.inc - FontHeight:=-11. Компилирую и все становится на свои места, но! После закрытия и открытия проекта файл unit1_1.inc перегенерируется заново и снова все через опу. Почему игнорит КОЛ - я хз. Имхо при записи кода создания формы в unit1_1.inc надо принудительно выставить параметры шрифта, либо искать где он гадит, если шрифт не задан и используется дефолтный. Далее: в dfm объект формы стоит первым. У всех контролов в dfm Font.FontHeight = -13. Откуда??? Я не задавал -13 вообще. С какого потолка оно взято? И почему KOL берет значения свойств из TForm, а не из TKOLForm??? Помогло только принудительное создание шрифта DefFont procedure TForm1.KOLForm1BeforeCreateWindow(Sender: PObj);
begin
DeleteObject(Form.Font.ReleaseHandle);
Form.Font.Assign(NewFont);
end;
-
Если вдруг интересно кому - то вырезал кучу старого хлама из KOL.pas (типа нерабочей Linux поддержки, "очень важной" поддержки делфи 2 и т.д). Cкинул на свн https://sourceforge.net/projects/kolmck/зы. возможно что отвалилось\сломалось...
-
http://clavier.link (язык AL-IV - АЛФОР): 18.05.2017 v0.62 Добавлена поддержка платформы Win32/Delphi/KOL (версия KOL 3.23) - на данный момент только не визуальной его части (работа продолжается).
-
Столкнулся с глюком TBitmap. Гружу 24-битное, преобразовываю дизерингом в 8-битное. Затем мне надо, чтобы размеры (если они меньше заданных) были подогнаны под один и тот же размер (добавляются поля черного). Так вот после увеличения только ширины картинки изображение становится 32-битным (с какого перепугу??). Если сначала увеличить высоту, а потом ширину, то изображение остается 8-битным.
-
> Vladimir Kladov © (17.05.17 21:15) [88]
регистрозависимость это дичь .... нет элементарной документации аля "хеловёрд" по спецификациям начать что то писать невозможно
-
Привет спецам! Помогите пжлст. Под андрюшу вышел бинарный транслятор x86 в ARM от программистов из Сколково, что писали нечто подобное под Эльбрус. В общем эти ребята в Play Market выложили свое творение - wine 1.9, работающий под андройдом на любом ARM устройстве. Там они его распространяют преимущественно для запуска старых игр. Называется ExaGear. И действительно, на нем работает куча программ. Но только не мои, написанные на delphi с применением библиотеки KOL. А так хотелось..... Вылетает даже минимальная программа, создающая пустую форму. Вот скрин https://s1.postimg.org/vkb1liaan/20170722_005204.jpgКомпилирую в delphi 6, запущенной в этой среде. Отладчик не ссылается ни на какой участок кода. Как узреть, что именно приводит к вылету?
-
по функции: function Extended2Str( E: Extended ): KOLString;
нужно кроме предвартельной проверки E на 0, еще добавить проверку на Infinity и NAN, иначе уйдет в бесконечный цикл.
-
Сделал для себя новый Format для КОЛ - старый слишком убог по функционалу. Абсолютно весь функционал вводить не стал, взял только самое распространенное.
function vsprintf_s(Buffer: PChar; BufferSize: integer; const Fmt: PChar; Args: pointer): integer; cdecl; external 'msvcrt.dll';
function Format(const Fmt: string; Params: array of const): string;
var
VA,Tmp: PByte;
Buffer: array[0..4095] of Char;
I,A,Size: integer;
D: double;
begin
FillChar(Buffer,sizeof(Buffer),0);
if High(Params)>=0 then
begin
Size:=0;
for I:=0 to High(Params) do
with Params[I] do
case VType of
vtInteger: Inc(Size,sizeof(Integer));
vtChar: Inc(Size,sizeof(Char));
vtWideChar: Inc(Size,sizeof(WideChar));
vtPChar,vtAnsiString,vtPWideChar,vtWideString,vtPointer: Inc(Size,sizeof(Pointer));
vtExtended: Inc(Size,sizeof(Double));
end;
GetMem(VA,Size);
FillChar(VA^,Size,0);
Tmp:=VA;
for I:=0 to High(Params) do
begin
A:=sizeof(Pointer);
with Params[I] do
case VType of
vtInteger:
begin
A:=sizeof(Integer);
PInteger(Tmp)^:=VInteger;
end;
vtChar:
begin
A:=sizeof(Char);
PChar(Tmp)^:=VChar;
end;
vtPChar: PPointer(Tmp)^:=VPChar;
vtAnsiString: PPointer(Tmp)^:=VString;
vtWideChar:
begin
A:=sizeof(WideChar);
PWideChar(Tmp)^:=VWideChar;
end;
vtPWideChar: PPointer(Tmp)^:=VPWideChar;
vtWideString: PPointer(Tmp)^:=VWideString;
vtExtended:
begin
A:=sizeof(Double);
D:=VExtended^;
PDouble(Tmp)^:=D;
end;
end;
Inc(Tmp,A);
end;
I:=vsprintf_s(@Buffer[0],4096,PChar(Fmt),VA);
if I>0 then
begin
SetLength(Result,I);
Result:=Buffer;
end;
if VA<>nil then FreeMem(VA);
end;
end;
Все символы описаны в https://msdn.microsoft.com/ru-ru/library/hf4y5e3w.aspx
-
> L`Autour (01.08.17 10:27) [92] > по функции:function Extended2Str( E: Extended ): KOLString; > нужно кроме предвартельной проверки E на 0, еще добавить > проверку на Infinity и NAN, иначе уйдет в бесконечный цикл. >
незнай как там с проверками, но Extended2Str в 6 раз!!! медленней стандартной Str и в 4.5 раз FloatToStr из сисутилсов
-
>Сделал для себя новый Format для КОЛ - старый слишком убог по функционалу.
А в чем убогость то заключается? Вроде основное все было..
>незнай как там с проверками, но Extended2Str в 6 раз!!! медленней стандартной Str и в 4.5 раз FloatToStr из сисутилсов
Получается у Extended2Str нет никаких преимуществ перед стандартной Str?
-
> Получается у Extended2Str нет никаких преимуществ перед > стандартной Str?
нету, так же как и у FloatToSt,IntToStr,Int2Str
-
И как же KOLString, UNICODE_CTRLS?
-
> И как же KOLString, UNICODE_CTRLS?
а без разницы, Str в топе
-
>> А в чем убогость то заключается? Вроде основное все было.. Типа старые функции небезопасны. И старый Format не поддерживает и половины возможностей. Насколько помню, плавающий формат он не переваривал. Была доработка, но она криво отображала float.
-
если не ошибаюсь, в ТВижн чё то такое было, и с плавающими итп... без всяких vsprintf_s. по крайней мере видел в исходниках Дос Навигатора
-
Бился сейчас с bitmap. До чего же он кривой!
1) Assign иногда работает, иногда падает на ровном месте. В частности пытался сделать копию одного битмапа в другом, так после assign второй битмап упал на Free. 2) Проблема была в глюке, когда присваиваешь ширину (или высоту, не помню уже сейчас), потом ее увеличиваешь, а потом уменьшаешь и scanline пользоваться невозможно = nil. 3) NewDIBBitmap(ширина,высота,pf4bit) - делаем битмап подобным другому. Но scanline выдает nil. А достаточно сделать Canvas.FillRect(BoundsRect), чтоб залить всю канву черным (и, тем самым, "включить" наконец scanline) и все нормализуется. Спрашивается, какого хрена? По идее мы создали битмап, данные указаны, память под битовые данные выделена, а данных на самом деле нет.
Имхо надо выбрасывать этот глюкавый битмап и делать на основе стандартного новый.
-
Ну, так поправить Bitmap чтобы выделял память после создания и все свойства корректно заполнял (если текущее поведение не было сделано с целью отодвинуть алокацию ресурсов до первого использования - тогда надо искать/добавить возможность делать это по требованию).
-
Так если бы это было только в этом. А с падениями на Free после Assign или (о, боже!) SaveToFile после работы со scanline, которые вылетают в ntdll, как быть? Ошибка в коде исключена - тоже самое в VCL работает без запинки. Вышеописанное на одном изображении проходит нормально, на следующем - падает. Причем меняешь изображения местами - сначала падающее, потом нет - все равно на втором падает.
-
Кстати, в NewDIBBitmap память для DIBBits выделяется сразу, но непонятно, почему scanline выдает nil. И на кой черт в GetScanline:
Result := Pointer( PAnsiChar( fDIBBits ) + fScanLineSize * Y );
указатель fDIBBits оборачивается PAnsiChar?? Откуда такая дичь? Мб тут проблема? Неужели сложно сделать:
Result := Pointer( DWORD( fDIBBits ) + fScanLineSize * Y );
-
> Откуда такая дичь?
Ну, так арифметика с Pointer-ами (до недавнего времени) работает только с PAnsiChar(). Так и привыкли.
> Мб тут проблема?
Да, вроде, вполне безобидный код. Возвратит лажу, если fDIBBits указывает на что-то левое или fScanLineSize вычислен неправильно.
-
Проблему с падением при уменьшении глубины цвета решил - тупо загнал одинаковые палитры в битмапы и отрисовал большую глубину на меньшую. Все "сконвертилось", палитра не искажена, запись и удаление без вылетов. Костыль, конечно, но другого выхода пока нет.
-
> отрисовал большую глубину на меньшую
А разве есть какой-то другой способ?
-
>> А разве есть какой-то другой способ? Руками. Тем более, если палитра заранее неизвестна (дизеринг). В данном случае палитра была известна и "умещалась" в 16 цветов. Но могут быть варианты, когда исходная палитра имеет цветов больше, чем результирующая.
|