为什么在 Fortran 中使用未初始化的变量会起作用?

Why would using uninitialized variables in Fortran ever work?

我一直在研究一些 30 多年前的 Fortran 代码,试图找出为什么它只是间歇性地因为看似随机的原因而不起作用。一组输入适用于一个用户但不适用于另一个用户,代码在使用 -O1 或 -O3 编译时有效但使用 -O2 时出现段错误,以及其他奇怪的废话。

在30年没碰过的代码里挑了大约一个星期后,我找到了问题——有很多未初始化的变量,不管是不是随机垃圾,基本上都是随机的这些变量中的 up 会使整个程序崩溃。老实说,我不知道这段代码是如何工作的。

现在我回到我的客户那里并告诉他们发生了什么,他们的回答是“如果这是一个问题,为什么代码在过去 30 年中一直有效......?”这是一个公平的问题——为什么这个代码在过去 30 年里对他们有效?我想我是第一个从那时起从源代码重建它的人,90 年代的 Fortran 编译器是否将堆栈归零或其他什么?为什么几十年前的程序员认为将变量放在赋值运算符的右侧而不考虑这些变量是否已先初始化是合理的?

在这里退休的 Fortran 编译器开发人员。它(通常)用于工作的原因是在 Fortran 90 之前,局部变量可以是静态的,而不是在堆栈上,并且链接器通常将静态数据初始化为零。是的,有支持堆栈分配和递归的 FORTRAN 77 编译器,但您可以编写一个完全 standard-conforming 没有堆栈分配的编译器。

因为“它有效”,所以假定这是程序员的正确方法。这也是为什么如此多的 F90+ 编译器必须向 zero-initialize 变量添加一个选项(或使所有局部变量保存,标准没有说明的另一件事),以使旧的损坏代码继续工作。

程序员做的很多其他事情虽然无效但“有效”,例如故意越界访问数组、参数类型不匹配、跳入循环中间等等。随着编译器越来越多先进的,许多这些“技巧”停止工作,用户抱怨。我早就忘记了我不得不告诉用户的次数,不,编译器没有破坏他们的代码,它总是被破坏。