trace
-
NAME
- trace — Отслеживание доступа к переменным, использования команд и выполнения команд
- SYNOPSIS
- DESCRIPTION
-
trace add type name ops ?args?
-
trace add command name ops commandPrefix
-
rename
- delete
- trace add execution name ops commandPrefix
-
enter
- leave
- enterstep
- leavestep
- leave
- trace add variable name ops commandPrefix
-
array
- read
- write
- unset
- read
-
rename
- trace remove type name opList commandPrefix
-
trace remove command name opList commandPrefix
- trace remove execution name opList commandPrefix
- trace remove variable name opList commandPrefix
- trace remove execution name opList commandPrefix
- trace info type name
-
trace info command name
- trace info execution name
- trace info variable name
- trace info execution name
-
trace add command name ops commandPrefix
-
trace variable name ops command
- trace vdelete name ops command
- trace vinfo name
- trace vdelete name ops command
- ПРИМЕРЫ
- СМОТРИТЕ ТАКЖЕ
- КЛЮЧЕВЫЕ СЛОВА
-
trace variable name ops command
- trace vdelete name ops command
- trace vinfo name
- trace vdelete name ops command
Имя
trace — Отслеживание доступа к переменным, использования команд и выполнения командСинтаксис
trace опция ?arg arg ...?Описание
Данная команда вызывает выполнение Tcl-команд всякий раз, когда вызываются определенные операции. Допустимые опции (которые можно сократить) следующие:- trace add type name ops ?args?
- Где type — command, execution или variable.
- trace add command name ops commandPrefix
- Организует выполнение commandPrefix (с дополнительными аргументами) всякий раз, когда команда name изменяется одним из способов, указанных в списке ops. Name будет разрешен с использованием стандартных правил разрешения имен, используемых командами. Если команда не существует, будет выброшено сообщение об ошибке.
Ops указывает, какие операции представляют интерес, и является списком одного или нескольких из следующих элементов:
- переименование
- Вызывает commandPrefix всякий раз, когда отслеживаемая команда переименовывается. Обратите внимание, что переименование в пустую строку считается удалением и не будет отслеживаться с помощью «переименования».
- удаление
- Вызывает commandPrefix, когда отслеживаемая команда удаляется. Команды можно удалить явно, используя команду переименование для переименования команды в пустую строку. Команды также удаляются при удалении интерпретатора, но слежения не будут вызваны, поскольку нет интерпретатора, в котором их можно выполнить.
Когда срабатывает отслеживание, в зависимости от отслеживаемых операций, к commandPrefix добавляется ряд аргументов, так что фактическая команда выглядит следующим образом:
commandPrefix oldName newName op
OldName и newName указывают текущее (старое) имя отслеживаемой команды и имя, на которое она переименовывается (пустая строка, если это операция «удаления»). Op указывает выполняемую операцию над командой и является одним из переименования или удаления, как определено выше. Операция отслеживания не может использоваться для предотвращения удаления команды. Tcl всегда удалит команду по завершении отслеживания. Рекурсивное переименование или удаление не приведет к дальнейшему оцениванию слежений того же типа, поэтому слежение на удаление, которое само удаляет команду, или слежение на переименование, которое само переименовывает команду, не приведет к дальнейшему оцениванию слежений. И oldName, и newName полностью квалифицированы с любыми именованными пространствами, в которых они появляются.
- trace add execution name ops commandPrefix
- Организует выполнение commandPrefix (с дополнительными аргументами) всякий раз, когда команда name выполняется, при этом слежения происходят в точках, указанных в списке ops. Name будет разрешен с использованием стандартных правил разрешения имен, используемых командами. Если команда не существует, будет выброшено сообщение об ошибке.
Ops указывает, какие операции представляют интерес, и является списком одного или нескольких из следующих элементов:
- вход
- Вызывает commandPrefix всякий раз, когда команда name выполняется непосредственно перед фактическим выполнением.
- выход
- Вызывает commandPrefix всякий раз, когда команда name выполняется непосредственно после фактического выполнения.
- шаг_входа
- Вызывает commandPrefix для каждой Tcl-команды, которая выполняется с начала выполнения процедуры name до завершения этой процедуры. CommandPrefix вызывается непосредственно перед фактическим выполнением сообщаемой Tcl-команды. Например, если у нас есть «proc foo {} { puts "hello" }», то отслеживание шаг_входа будет вызвано непосредственно перед выполнением «puts "hello"». Установка отслеживания шаг_входа для команды name, которая не ссылается на процедуру, не приведет к ошибке и просто игнорируется.
- шаг_выхода
- Вызывает commandPrefix для каждой Tcl-команды, которая выполняется с начала выполнения процедуры name до завершения этой процедуры. CommandPrefix вызывается непосредственно после фактического выполнения сообщаемой Tcl-команды. Установка отслеживания шаг_выхода для команды name, которая не ссылается на процедуру, не приведет к ошибке и просто игнорируется.
Когда срабатывает отслеживание, в зависимости от отслеживаемых операций, к commandPrefix добавляется ряд аргументов, так что фактическая команда выглядит следующим образом:
Для операций вход и шаг_входа:
commandPrefix command-string op
Строка_команды предоставляет полную текущую команду, выполняемую (отслеживаемую команду для операции вход, произвольную команду для операции шаг_входа), включая все аргументы в их полностью расширенном виде. Op указывает выполняемую операцию над выполнением команды и является одним из вход или шаг_входа, как определено выше. Операция отслеживания может использоваться для остановки выполнения команды, удалив соответствующую команду. Конечно, при последующем выполнении команды появится ошибка «недействительная команда».
Для операций выход и шаг_выхода:
commandPrefix command-string code result op
Строка_команды предоставляет полную текущую команду, выполняемую (отслеживаемую команду для операции вход, произвольную команду для операции шаг_входа), включая все аргументы в их полностью расширенном виде. Код предоставляет код результата этого выполнения, а результат — строку результата. Op указывает выполняемую операцию над выполнением команды и является одним из выход или шаг_выхода, как определено выше. Обратите внимание, что создание многих слежений шаг_входа или шаг_выхода может привести к неинтуитивным результатам, поскольку вызываемые команды из одного слежения сами могут привести к дальнейшим вызовам команд для других слежений.
CommandPrefix выполняется в том же контексте, что и код, который вызвал отслеживаемую операцию: таким образом, commandPrefix, если он вызывается из процедуры, будет иметь доступ к тем же локальным переменным, что и код в процедуре. Этот контекст может отличаться от контекста, в котором было создано отслеживание. Если commandPrefix вызывает процедуру (что обычно и происходит), то процедуре необходимо использовать команды upvar или uplevel, если она хочет получить доступ к локальным переменным кода, который вызвал операцию отслеживания.
Пока commandPrefix выполняется во время отслеживания выполнения, отслеживания для name временно отключаются. Это позволяет commandPrefix выполнить name в своем теле без повторного вызова других отслеживаний. Если при выполнении commandPrefix произойдет ошибка, вся команда name вернёт эту ошибку.
При установке нескольких отслеживаний на name, для операций вход и шаг_входа, отслеживаемые команды вызываются в обратном порядке их первоначального создания; а для операций выход и шаг_выхода, отслеживаемые команды вызываются в исходном порядке создания.
Поведение отслеживаний выполнения в настоящее время не определено для команды name, импортированной в другое пространство имен.
- trace add variable name ops commandPrefix
- Установите выполнение commandPrefix всякий раз, когда переменная name обращается одним из способов, указанных в списке ops. Name может ссылаться на обычную переменную, элемент массива или массив в целом (т. е. name может быть просто именем массива без скобок с индексом). Если name ссылается на весь массив, то commandPrefix вызывается всякий раз, когда изменяется любой элемент массива. Если переменная не существует, она будет создана, но не будет иметь значения, поэтому она будет видна командам запроса пространства имён, но не командам запроса информации.
Ops указывает, какие операции представляют интерес, и является списком одного или нескольких следующих пунктов:
- массив
- Вызовите commandPrefix всякий раз, когда к переменной обращаются или изменяют её с помощью команды массив, при условии, что name не является скалярной переменной в момент вызова команды массив. Если name является скалярной переменной, доступ через команду массив не будет вызывать трассировку.
- чтение
- Вызовите commandPrefix всякий раз, когда переменная считывается.
- запись
- Вызовите commandPrefix всякий раз, когда переменная записывается.
- удаление
- Вызовите commandPrefix всякий раз, когда переменная удаляется. Переменные могут быть удалены явно с помощью команды unset или неявно, когда процедуры возвращают значения (все их локальные переменные удаляются). Переменные также удаляются при удалении интерпретаторов, но трассировки не будут вызваны, так как нет интерпретатора для их выполнения.
При срабатывании трассировки к commandPrefix добавляются три аргумента, так что фактическая команда будет следующей:
commandPrefix name1 name2 op
Name1 и name2 указывают имя(а) переменной, к которой происходит доступ: если переменная скалярная, то name1 указывает имя переменной, а name2 пустая строка; если переменная является элементом массива, то name1 указывает имя массива, а name2 индекс в массиве; если весь массив удаляется, и трассировка была зарегистрирована на массиве в целом, а не на отдельном элементе, то name1 указывает имя массива, а name2 пустая строка. Name1 и name2 не обязательно совпадают с именем, используемым в команде отслеживания переменной: команда upvar позволяет процедуре ссылаться на переменную под другим именем. Op указывает, какая операция выполняется над переменной, и является одной из чтение, запись или удаление, как определено выше.
CommandPrefix выполняется в том же контексте, что и код, вызвавший отслеживаемую операцию: если переменная была обращена в рамках Tcl-процедуры, то commandPrefix будет иметь доступ к тем же локальным переменным, что и код в процедуре. Этот контекст может отличаться от контекста, в котором была создана трассировка. Если commandPrefix вызывает процедуру (что обычно и происходит), то процедура должна использовать upvar или uplevel, если она хочет получить доступ к отслеживаемой переменной. Обратите также внимание, что name1 может не совпадать с именем, использованным для установки отслеживания на переменной; различия могут возникнуть, если доступ осуществляется через переменную, определенную с помощью команды upvar.
Для трассировок чтения и записи commandPrefix может изменить переменную, чтобы повлиять на результат отслеживаемой операции. Если commandPrefix изменяет значение переменной во время трассировки чтения или записи, то новое значение будет возвращено в качестве результата отслеживаемой операции. Возвращаемое значение от commandPrefix игнорируется, за исключением того, что если оно возвращает ошибку любого типа, то отслеживаемая операция также возвращает ошибку с тем же сообщением об ошибке, что и команда отслеживания (с помощью этого механизма можно, например, реализовать только для чтения переменные). Для трассировок записи commandPrefix вызывается после того, как значение переменной было изменено; он может записать новое значение в переменную, чтобы переопределить исходное значение, указанное в операции записи. Для реализации переменных только для чтения commandPrefix должен восстановить старое значение переменной.
Пока commandPrefix выполняется во время трассировки чтения или записи, трассировки переменной временно отключаются. Это означает, что чтение и запись, вызываемые commandPrefix, будут выполняться напрямую, без повторного вызова commandPrefix (или других трассировок). Однако, если commandPrefix удаляет переменную, то вызовутся трассировки удаления.
Когда вызывается трассировка удаления, переменная уже удалена: она будет казаться неопределенной без трассировок. Если удаление происходит из-за возврата процедуры, то трассировка будет вызвана в контексте переменной возвращаемой процедуры: кадр стека возвращаемой процедуры больше не будет существовать. Трассировки не отключаются во время трассировок удаления, поэтому если команда трассировки удаления создаёт новую трассировку и обращается к переменной, трассировка будет вызвана. Любые ошибки в трассировках удаления игнорируются.
Если на переменной установлено несколько трассировок, они вызываются в порядке создания, начиная с последней. Если одна трассировка возвращает ошибку, то дальнейшие трассировки для переменной не вызываются. Если у элемента массива установлена трассировка, и также установлена трассировка на весь массив, то трассировка для всего массива вызывается перед трассировкой для элемента.
После создания трассировка остается в силе до тех пор, пока она не будет удалена с помощью команды trace remove variable, описанной ниже, пока переменная не будет удалена или пока не будет удалён интерпретатор. Удаление элемента массива удалит любые трассировки для этого элемента, но не удалит трассировки для всего массива.
Эта команда возвращает пустую строку.
- Установите выполнение commandPrefix всякий раз, когда переменная name обращается одним из способов, указанных в списке ops. Name может ссылаться на обычную переменную, элемент массива или массив в целом (т. е. name может быть просто именем массива без скобок с индексом). Если name ссылается на весь массив, то commandPrefix вызывается всякий раз, когда изменяется любой элемент массива. Если переменная не существует, она будет создана, но не будет иметь значения, поэтому она будет видна командам запроса пространства имён, но не командам запроса информации.
- trace remove type name opList commandPrefix
- Где type может быть command, execution или variable.
- trace remove command name opList commandPrefix
- Если на команде name установлена трассировка с операциями и командой, заданными opList и commandPrefix, то трассировка удаляется, так что commandPrefix больше никогда не будет вызываться. Возвращает пустую строку. Если name не существует, команда выведет ошибку.
- trace remove execution name opList commandPrefix
- Если на команде name установлена трассировка с операциями и командой, заданными opList и commandPrefix, то трассировка удаляется, так что commandPrefix больше никогда не будет вызываться. Возвращает пустую строку. Если name не существует, команда выведет ошибку.
- trace remove variable name opList commandPrefix
- Если на переменной name установлена трассировка с операциями и командой, заданными opList и commandPrefix, то трассировка удаляется, так что commandPrefix больше никогда не будет вызываться. Возвращает пустую строку.
- trace info type name
- Где type может быть command, execution или variable.
- trace info command name
- Возвращает список, содержащий один элемент для каждой текущей трассировки на команде name. Каждый элемент списка сам является списком, содержащим два элемента, которые являются opList и commandPrefix, связанными с трассировкой. Если на name не установлено никаких трассировок, результатом команды будет пустая строка. Если name не существует, команда выведет ошибку.
- trace info execution name
- Возвращает список, содержащий один элемент для каждой текущей трассировки на команде name. Каждый элемент списка сам является списком, содержащим два элемента, которые являются opList и commandPrefix, связанными с трассировкой. Если на name не установлено никаких трассировок, результатом команды будет пустая строка. Если name не существует, команда выведет ошибку.
- trace info variable name
- Возвращает список, содержащий один элемент для каждой текущей трассировки на переменной name. Каждый элемент списка сам является списком, содержащим два элемента, которые являются opList и commandPrefix, связанными с трассировкой. Если name не существует или на ней не установлены трассировки, результатом команды будет пустая строка.
Для обратной совместимости доступны три других подкоманды:
- trace variable name ops command
- Это эквивалентно trace add variable name ops command.
- trace vdelete name ops command
- Это эквивалентно trace remove variable name ops command
- trace vinfo name
- Это эквивалентно trace info variable name
Эти подкоманды устарели и, вероятно, будут удалены в будущей версии Tcl. Они используют более старую синтаксическую конструкцию, в которой массив, чтение, запись, unset заменяются соответственно на a, r, w и u, а аргумент ops не является списком, а просто строковым объединением операций, например, rwua.
Примеры
Выведите сообщение всякий раз, когда глобальные переменные foo и bar обновляются, даже если у них другое локальное имя в данный момент (что можно сделать с помощью команды upvar):proc tracer {varname args} {
upvar #0 $varname var
puts "$varname was updated to be \"$var\""
}
trace add variable foo write "tracer foo"
trace add variable bar write "tracer bar" Убедитесь, что глобальная переменная foobar всегда содержит произведение глобальных переменных foo и bar:
proc doMult args {
global foo bar foobar
set foobar [expr {$foo * $bar}]
}
trace add variable foo write doMult
trace add variable bar write doMult Выведите трассировку команд, выполняемых во время обработки Tcl-процедуры:
proc x {} { y }
proc y {} { z }
proc z {} { puts hello }
proc report args {puts [info level 0]}
trace add execution x enterstep report
x
→ report y enterstep
report z enterstep
report {puts hello} enterstep
hello См. также
set, unset
Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/TclCmd/trace.htm
Licensed under Tcl/Tk terms
https://www.tcl.tk/man/tcl/TclCmd/trace.htm