也可以定义每个 D 程序子句将重用其存储空间的 D 变量。子句局部变量与 C、C++ 或 Java 语言程序中的自动变量类似,这些变量在每次调用函数期间处于活动状态。与所有 D 程序变量一样,子句局部变量会在首次赋值时自动创建。通过将 -> 运算符应用于特殊标识符 this 可引用这些变量并对这些变量赋值:
BEGIN { this->secs = timestamp / 1000000000; ... }
如果要在使用子句局部变量前对其进行显式声明,可使用 this 关键字进行声明:
this int x; /* an integer clause-local variable */ this char c; /* a character clause-local variable */ BEGIN { this->x = 123; this->c = 'D'; }
子句局部变量仅在给定探测子句的生命周期中处于活动状态。在 DTrace 执行与给定探测器的子句关联的操作后,将会回收所有子句局部变量的存储空间,并重用于下一条子句。因此,子句局部变量是唯一不使用零进行初始填充的 D 变量。请注意,如果程序的单个探测器包含多条子句,在执行这些子句时,所有子句局部变量将会保持不变,如下例所示:
int me; /* an integer global variable */ this int foo; /* an integer clause-local variable */ tick-1sec { /* * Set foo to be 10 if and only if this is the first clause executed. */ this->foo = (me % 3 == 0) ? 10 : this->foo; printf("Clause 1 is number %d; foo is %d\n", me++ % 3, this->foo++); } tick-1sec { /* * Set foo to be 20 if and only if this is the first clause executed. */ this->foo = (me % 3 == 0) ? 20 : this->foo; printf("Clause 2 is number %d; foo is %d\n", me++ % 3, this->foo++); } tick-1sec { /* * Set foo to be 30 if and only if this is the first clause executed. */ this->foo = (me % 3 == 0) ? 30 : this->foo; printf("Clause 3 is number %d; foo is %d\n", me++ % 3, this->foo++); }
因为子句始终按程序顺序执行,且子句局部变量在启用相同探测器的不同子句中具有持久性,所以运行上述程序将始终产生同样的输出:
# dtrace -q -s clause.d Clause 1 is number 0; foo is 10 Clause 2 is number 1; foo is 11 Clause 3 is number 2; foo is 12 Clause 1 is number 0; foo is 10 Clause 2 is number 1; foo is 11 Clause 3 is number 2; foo is 12 Clause 1 is number 0; foo is 10 Clause 2 is number 1; foo is 11 Clause 3 is number 2; foo is 12 Clause 1 is number 0; foo is 10 Clause 2 is number 1; foo is 11 Clause 3 is number 2; foo is 12 ^C |
虽然子句局部变量在启用相同探测器的各条子句中具有持久性,但在为给定探测器执行的第一条子句中,未定义这些变量的值。在使用每条子句局部变量前,请务必为其指定相应的值,否则程序可能产生意外结果。
可使用任何标量变量类型定义子句局部变量,但不可以使用子句局部作用域定义关联数组。子句局部变量的作用域仅适用于相应的变量数据,而不适用于为变量定义的名称和类型标识。一旦定义子句局部变量,就可以在任何后续 D 程序子句中使用该名称和类型签名。存储位置在不同子句中不会一直保持不变。
可以使用子句局部变量积累计算的中间结果,或作为其他变量的临时副本。访问子句局部变量要比访问关联数组快得多。因此,如果需要在同一个 D 程序子句中多次引用关联数组值,首先将该值复制到一条子句局部变量中,然后重复引用该局部变量,将获得更高的效率。