编译器如何检测未分配的局部变量的使用?

时间:2015-06-24 18:45:35

标签: compiler-construction language-agnostic variable-assignment variable-initialization

如果您尝试使用尚未(肯定)已分配/初始化的局部变量,则Java或C#等语言的编译器会抱怨。

我想知道在编译器中如何实现该功能。显然,有关变量初始化状态的信息可以保存为布尔标志,并在检测到赋值语句后进行相应设置。但是(嵌套的)子范围如循环体或条件语句呢?

2 个答案:

答案 0 :(得分:2)

这可以实现计算活跃度信息。

编译器通常将源代码转换为较低级别的中间表示(IR),将该代码划分为基本块(无效代码),并从那里构建控制流图(CFG)。

活跃度分析可以为每个基本块计算LiveOut集。如果变量在某个基本块的LiveOut集中,则表示该变量将在后续块中使用而不会被杀死(分配给)。

CFG有两个特殊节点:ENTRY节点和EXIT节点。 如果变量位于ENTRY节点的LiveOut集中,则表示该变量将在未分配给值之前使用。

指针可能会使此分析复杂化。 例如,请考虑以下代码

 int *p, x, y;
 ...
 *p = 123;
 y = x*2;

为了不报告误报,编译器必须执行所谓的指针分析。这个分析所做的是为每个指针计算指针可能(或必须)指向的有效目标集。 在上面的例子中,如果编译器发现p指向x,那么当在后面的行中使用x时,x不是未初始化的。

答案 1 :(得分:0)

这相对容易。每个可能的代码执行路径必须在使用变量之前导致赋值。循环也被视为可能的路径;重复对于这种分析无关紧要。