|
FAQ Туториалы и часто задаваемые вопросы |
10.01.2006, 18:14
|
#1
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
"DebugLog и память" или "юзаем аккуратно".
На создание этой заметки меня сподвиг факт существования культа авторитета и культа мнения большинства.
Или как называл эти тормозящие процесс познания явления Френсис Бэкон: призраки рынка и призраки театра.
Но не будем вдаваться в подробности поиска метода познания в период Нового Времени и вернёмся к b3d.
Помнится многие рьяно уверяли меня в том, что b3d адекватно отображает кирилический текст произвольной длины командой Text...
Пока Morpher и Tormoz не подтвердили этот обидный недостаток... Часто проблема обнаружения уязвимости заключается в сложности провоцирования ошибки.
На этот раз сбой при выполнении команды Debuglog.
К сожалению чётко сформулировать условия сбоя пока не удалось, но происходит он при
многократном вызове функций ( в т.ч. рекурсивно) и юзании конструкций типа:
Function a(x)
DebugLog x
Return x
End Function
DebugLog a(x)
В приведённом ниже примере, уменьшение кол-ва вызовов команды debuglog ведёт к повышению устойчивости, а запуск программы вне отладочного режима ( что эквивалентно полному избавлению кода от команд отладки) даёт 100%-правильный результат вычилений при любом кол-ве вызовов.
Собственно, сам пример:
В примере набо функций и тип для выичсления определителя кв.матрицы произвольного ограниченного размера.
Конкретно считается вот такой определитель:
Нетрудно заметить пропорциональность строк, на основании чего сделать вывод - матрица имеет нулевой
детерминант.
Вот b3d реализация:
Graphics 800,600
SetFont LoadFont("arial cur",20)
Const TMatrixMaxIndex2D=99
Type TMatrix
Field Buffer#[TMatrixMaxIndex2D]
Field StringSize
Field CSize
End Type
Function TMatrix_Create.TMatrix(size,size2=-1)
M.TMatrix=New TMatrix
M\StringSize=size
M\CSize=size2
If M\CSize=-1 M\CSize=size
Return M
End Function
Function TMatrix_IN(M.TMatrix,SNumber,CNumber,Z$)
Local Index2d=(SNumber-1)*M\StringSize+(CNumber-1)
M\Buffer[Index2d]=Z$
End Function
Function TMatrix_OUT(M.TMatrix,SNumber,CNumber)
Local Index2d=(SNumber-1)*M\StringSize+(CNumber-1)
Return M\Buffer[Index2d]
End Function
Function TMatrix_Delete(M.TMatrix)
Delete M
End Function
Function TMatrix_Determinant#(M.TMatrix)
SS=M\StringSize
CS=M\CSize
If SS=1 And CS=1
DebugLog "determ ="+M\buffer[0]
Return Float(M\buffer[0])
EndIf
Local DET#=0
For i=1 To SS
*MINOR.TMATRIX=TMatrix_minor(M,1,i)
*DebugLog ""+DET+"+"+((-1)^(i+1))+"*"+TMatrix_Determinant(MINOR)+"*"+TMatrix_OUT(M,1,i)
*DET=DET+(-1)^(i+1)*TMatrix_Determinant(MINOR)*Float(TMatrix_OUT(M,1,i))
*DebugLog "="+DEt
*TMatrix_Delete(MINOR)
Next
DebugLog "determ ="+DET
Return DET
End Function
Function TMatrix_minor.TMatrix(M.TMatrix,NS,NC)
minSS=M\StringSize-1
minCS=M\CSize-1
Minor.TMatrix=TMATRIX_Create(minSS,minCS)
Local Smin=1
For S=1 To M\CSize
*Local Cmin=1
*For C=1 To M\StringSize
* If C=NC
* Cmin=Cmin-1
* Else
* TMatrix_IN(Minor,Smin,Cmin,TMatrix_OUT(M,S,C))
* EndIf
* Cmin=Cmin+1
*Next
*If S=NS
*Smin=Smin-1
*EndIf
*Smin=Smin+1
Next
Return Minor
End Function
a.tmatrix=tmatrix_create(3,3)
TMatrix_IN(a,1,1,1)
TMatrix_IN(a,1,2,2)
TMatrix_IN(a,1,3,3)
TMatrix_IN(a,2,1,4)
TMatrix_IN(a,2,2,5)
TMatrix_IN(a,2,3,6)
TMatrix_IN(a,3,1,7)
TMatrix_IN(a,3,2,8)
TMatrix_IN(a,3,3,9)
For i=1 To 25
dd=TMatrix_Determinant(a)
DebugLog dd
Print "test#: "+i+"; * 0="+dd
Next
WaitKey()
End
Код вычурно перегружен отладочными командами и вызовами функций с целью показть уязвимость в действии.
Запустите его в ___ОТЛАДОЧНОМ____ режиме.
И понаблюдайте - сколько раз из 25 b3d докажет что 0<>0.
Теперь отключите отладку и сравните результаты. =)
Положив 2 часа на отладку полностью рабочего кода ( постоянно добавляя отладочные команды - чем ещё более усугублял совё положение) я перепробовал различные версии b3d - все подвержены данной ошибке, которая, судя по всему, заключается в затирании уже используемых пространств памяти.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
10.01.2006, 18:25
|
#2
|
Модератор
Регистрация: 13.09.2005
Сообщений: 1,835
Написано 6 полезных сообщений (для 10 пользователей)
|
гы... когда я услышал по скайпу ответ b3d этой матрицы (за минуту до этого проверил формулы написанные Импером) я почти упал со стула!
будьте осторожны!
|
(Offline)
|
|
10.01.2006, 22:06
|
#3
|
|
Originally posted by impersonalis@Jan 10 2006, 05:14 PM
Код вычурно перегружен отладочными командами и вызовами функций с целью показть уязвимость в действии.
Запустите его в ___ОТЛАДОЧНОМ____ режиме.
И понаблюдайте - сколько раз из 25 b3d докажет что 0<>0.
Теперь отключите отладку и сравните результаты. =)
Положив 2 часа на отладку полностью рабочего кода ( постоянно добавляя отладочные команды - чем ещё более усугублял совё положение) я перепробовал различные версии b3d - все подвержены данной ошибке, которая, судя по всему, заключается в затирании уже используемых пространств памяти.
|
К сожалению, это не баг, а всего лишь неграмотное применение отладчика в примере, который привел Impersonalis. Отлачик в функции TMatrix_Determinant рекурсивно вызывает эту же функцию, что, естественно, неизбежно вызывает исчерпание стека (хорошо еще, что встроенные отладчики имеют свою стековую машину, а то бы вообще все рунуло).
Правильно делать так:
Function TMatrix_Determinant#(M.TMatrix)
SS=M\StringSize
CS=M\CSize
If SS=1 And CS=1
DebugLog "determ ="+M\buffer[0]
Return Float(M\buffer[0])
EndIf
Local DET#=0
For i=1 To SS
MINOR.TMATRIX=TMatrix_minor(M,1,i)
TMD#=TMatrix_Determinant(MINOR)
DebugLog ""+DET+"+"+((-1)^(i+1))+"*"+TMD+"*"+TMatrix_OUT(M,1,i)
DET=DET+(-1)^(i+1)*TMD*Float(TMatrix_OUT(M,1,i))
DebugLog "="+DEt
TMatrix_Delete(MINOR)
Next
DebugLog "determ ="+DET
Return DET
End Function
Теперь никаких ошибок не будет.
В нормальном режиме и дебаггера достаточно ресурсов для своей работы.
Собственно, DebugLog предназначен для формирования строки вывода и имеет буфер строки более 16 Кбайт, это легко проверить с помощью
a$=""
For j=1 To 16000
For i=0 To 9
a$=a$+i
Next
Next
DebugLog a$
WaitKey
Разумеется, ничего не мешает Марку установить и размер стека, не вызывающий проблем в нормальном режиме - для простого блитца он может вообще иметь пару килобайт, а его переполнение ошибки не вызывает (что тоже странно, однако). Правда ошибки в блитце не вызывает и отсутствие вызываемой DLL при динамическом связывании, что не менее странно (а при статическом связывании при этом сразу появится ошибка).
В Help-файле написано, что аргументом DebugLog может быть текстовая переменная, строка, числовое значение. К сожалению, структура справки в целом нечеткая, поэтому трудно судить, запрещалось ли изначально в ней вычисление выражения. Но я пытался без рекурсии свалить стек, но при корректных вычислениях у меня не получилось. Но в любом случае, для вычисления выражений в приведенном Impersonalisom примере ограничивается стековое пространство при рекурсии.
Но есть программы, которые ведут себя странно со включенным Debug , причем DebugLog вообще там не используется, например партикловая система Lotus.
|
|
|
11.01.2006, 01:22
|
#4
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Ну в общем то целью заметки было предотвратить неосторожное юзание debuglog.
Ведь это сложнонаходимо.
Если переполнить стек программы она либо закрешится, либо молча зкроется - а тут всё считается.. но не правильно.
То что код так не пишут я знаю =)
Это пример.
В любом случае - спибо за автороитетное мнение и уточнение деталей.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
11.01.2006, 03:06
|
#5
|
|
Originally posted by impersonalis@Jan 11 2006, 12:22 AM
Ну в общем то целью заметки было предотвратить неосторожное юзание debuglog.
Ведь это сложнонаходимо.
Если переполнить стек программы она либо закрешится, либо молча зкроется - а тут всё считается.. но не правильно.
То что код так не пишут я знаю =)
Это пример.
В любом случае - спибо за автороитетное мнение и уточнение деталей.
|
1) Хорошо сказал - неосторожное юзанье!
DebugLog можно и нужно использовать.
2)Насчет сложнонаходимо - у меня это заняло 1 минуту с проверкой. А для того, чтобы потренироваться со стеком - надо на Форте попробовать попрограммировать - там одновременно несколько стеков используется, вот где раздолье!
3)Во-первых тут стек не программы, а отладчика. Отладчик работает, как вариант, сохраняя кадр программы и переключая регистр BP на другую область стека. А во-вторых, так как DebugLog чисто информационный, из-за переполнения стека может быть получен только недостоверный результат, поскольку вычисление функции может прерваться в любом месте, но при этом происходит восстановление кадра программы (всех регистров, стека и флагов). То есть краха программы не будет.
Поэтому считается все правильно, только в последней рекурсии, на которой выделенный стек загнулся, вычисление обрывается с итоговым неправильным состоянием регистров микропроцессора, которое выдаст в неправильный результат DET.
|
|
|
11.01.2006, 03:15
|
#6
|
|
P.S. Естественно, под BP подразумевается EBP или RBP.
|
|
|
11.01.2006, 03:27
|
#7
|
|
Имеется в виду, что ESP юзается обычно в связки с EPB. Вообщем, это уже не Бейсик.
Что-то я размазался по трем постам.... Зарегиться, что ли, чтобы править можно было...
|
|
|
11.01.2006, 04:14
|
#8
|
Зануда с интернетом
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений (для 20,935 пользователей)
|
Originally posted by AsmLover@Jan 11 2006, 02:27 AM
Зарегиться, что ли, чтобы править можно было...
|
ага
давно ждём, столь опытного кодера в своих рядах
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 18:42.
|