Обратное отслеживание по стеку

Интерпретация сообщений об ошибках

В ответ на выполнение сценария в MAXScript формируются сообщения об ошибках, помогающие определить вид ошибки и место ее возникновения. Примеры сообщений об ошибках уже приводились в предыдущем разделе, посвященном видам ошибок, в частности следующее сообщение:

for i = 1 to 10 print i

-- Syntax error: at end, expected "do" or "collect"

В этом сообщении указывается, что синтаксическая ошибка произошла в конце сценария, где предполагалось обнаружить зарезервированное слово do или collect.

А теперь рассмотрим пример сообщения об ошибке периода выполнения:

arr = #(1); arr[0]

-- Runtime error: array index must be +ve number, got: 0

В этом сообщении указывается, что ошибка времени выполнения возникла в связи с тем, что индекс массива должен быть положительным целым числом, ко­торое больше нуля, однако он оказался равным нулю.


Приложение

Далее рассмотрим пример ошибки времени компиляции:

(

y = (1/(х as float)

)

-- Compile error: Unexpected end-of-script

В этом сообщении указывается, что произошла ошибка времени компиляции. В частности, обнаружено неожиданное окончание сценария. Это произошло из-за пропуска круглой скобки в строке line y = (1/(х as float).

Системное исключение Unknown указывает на серьезную ошибку, которая может привести к нарушению устойчивой работы 3dsMax.

Сообщения об ошибках помогают отнюдь не всегда и могут даже ввести в заблуждение. Ведь сообщение об ошибке — это всего лишь попытка MAXScript распознать и обнаружить ошибку. Решению этой задачи препятствуют присущие данному процессу ограничения. Иногда MAXScript просто не в состоянии правильно распознать и обнаружить ошибку. Поэтому сообщение об ошибке может быть неопределенным, а место ошибки — указанным неверно. Но несмотря на подобные ограничения, сообщения об ошибках являются важным элементом отладки сценариев.

Сообщения об ошибках появляются в приемнике команд, а иногда и в перемещаемом диалоговом окне предупреждения. Текст сообщения в приемнике команд включает в себя информацию из окна предупреждения, а также результаты обратного отслеживания по стеку. В таком стеке отслеживается вся предыстория вызовов функций, обработчиков ошибок и выполнения циклов, включая ошибки, к которым это привело. Подобные сведения приводятся в обратном порядке по отношению к происходившим событиям, причем самое последнее из них находится в начале от­слеживаемой предыстории. Помимо этого, выводятся локальные переменные, пара­метры функций и их значения. Тщательный анализ подобной информации позволяет выявить подозрительные переменные и определить место возникновения ошибки.

Ниже приведен пример сценария, выполнение которого приводит к ошибке и появлению окна предупреждения вместе с результатами обратного отслеживания по стеку. В данном сценарии создается простое окно с единственной кнопкой. В обработчике событий данной кнопки вызывается простая функция, восприни­мающая один параметр. Эта функция содержит цикл, индекс которого умножается на параметр функции и неопределенную локальную переменную. Именно эта переменная дает ошибку.

Откройте приемник команд и выполните приведенный ниже сценарий в окне редактора MAXScript Editor. Щелкните на кнопке Click Me (Щелкни на мне).

fn testFunction n = (

for i = 1 to 10 do x = i * n * undefinedLocalVariable

)

try destroyDialog rol_test catch()

rollout rol_test "Test"

(


Приложение

button but_test "Click Me!"
on but_test pressed do
(

clearListener()
testFunction 123

)

)

createDialog rol_test

После того как вы щелкнете на кнопке ClickMe, появится приведенное ниже предупреждающее окно, в котором указывается ошибка несовместимости типов данных.

 

 


Эта ошибка возникла из-за того, что обработчик событий кнопки вызвал функцию и передал ей числовое значение 123 в качестве параметра. Затем в цикле данной функции была предпринята попытка умножить неопределенную переменную на 123.

Ниже приведены результаты обратного отслеживания по стеку, выводимые в окне приемника команд. В этом окне красным выделено место возникновения ошибки и само сообщение об ошибке, а синим, выделены параметры и локальные переменные с соответствующими значениями.

-- Error occurred in i loop

-- Frame:

-- undefinedLocalVariable: undefined

-- i: 1

-- x: undefined

-- called in testFunction()

-- Frame:

-- n: 123

-- called in but_test.pressed()

-- Frame:

>> MAXScript Rollout Handler Exception:

-- Incompatible types: 123, and undefined <<

Предыстория выполнения сценария отображается в обратном порядке. В первой строке указывается, что ошибка произошла в цикле. В строках, которые следуют после строки "Frame", перечислены локальные переменные цикла и их значения (обратите внимание на то, что индекс цикла i считается локальной переменной). В связи с тем что i = 1, ошибка возникла на первом же шаге цикла. Затем в предыстории указывается на то, что ошибка произошла в функции. В информации под заголовком "Frame" также перечисляются параметр функции и его значение. И наконец, обратите внимание, что ошибка началась с обработчика событий кнопки, а в последней строке содержатся заголовок предупреждающего окна и сообщение об ошибке.


Приложение

Кроме того, курсор помещается рядом с ошибочной строкой кода. В данном случае он находится рядом с закрывающей круглой скобкой, следующей сразу же после цикла, в котором произошла ошибка. Иногда MAXScript не в состоянии точно определить ошибочную строку кода, но, как правило, результат оказывается достаточно близким к истине, чтобы начать отладку кода сценария.

Обратное отслеживание по стеку может показаться поначалу не очень удобным средством обнаружения ошибок, хотя оно не очень сложное. В то же время оно дает немало важной и полезной информации для отладки. Если уделить немного времени, чтобы научиться правильно интерпретировать обратно отслеживаемую предысторию, это позволит значительно упростить отладку сценариев.