Solaris 动态跟踪指南

子句局部变量

也可以定义每个 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 变量。请注意,如果程序的单个探测器包含多条子句,在执行这些子句时,所有子句局部变量将会保持不变,如下例所示:


示例 3–2 clause.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 程序子句中多次引用关联数组值,首先将该值复制到一条子句局部变量中,然后重复引用该局部变量,将获得更高的效率。