如果您尝试使用尚未(肯定)已分配/初始化的局部变量,则Java或C#等语言的编译器会抱怨。
我想知道在编译器中如何实现该功能。显然,有关变量初始化状态的信息可以保存为布尔标志,并在检测到赋值语句后进行相应设置。但是(嵌套的)子范围如循环体或条件语句呢?
答案 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)
这相对容易。每个可能的代码执行路径必须在使用变量之前导致赋值。循环也被视为可能的路径;重复对于这种分析无关紧要。