"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 - все подвержены данной ошибке, которая, судя по всему, заключается в затирании уже используемых пространств памяти.