Fra*_*ank 0 fortran local-variables stack-memory
我一直在研究一些已有 30 多年历史的 Fortran 代码,试图找出为什么它会因为看似随机的原因间歇性地不起作用。一组输入适用于一个用户,但不适用于另一个用户,使用 -O1 或 -O3 编译时可以工作的代码,但使用 -O2 时会出现段错误,以及其他奇怪的废话。
经过大约一周的时间挑选了 30 年没有碰过的代码,我找到了问题所在——有很多未初始化的变量,而且这些变量中的随机垃圾是否崩溃基本上是随机的整个计划。老实说,我不知道这段代码是如何工作的。
现在我回到客户那里并告诉他们发生了什么事,他们的回答是“如果这是一个问题,为什么代码在过去 30 年里一直有效......?” 这是一个公平的问题——为什么这个代码在过去 30 年里对他们有效?我想我是从那时起第一个从源代码重建它的人,90 年代的 Fortran 编译器是否将堆栈归零或其他什么?为什么几十年前的程序员认为将变量放在赋值运算符的右侧是合理的,而不考虑这些变量是否已首先初始化?
这里是已退休的 Fortran 编译器开发人员。它(通常)工作的原因是,在 Fortran 90 之前,局部变量可以是静态的,不在堆栈上,并且链接器通常将静态数据初始化为零。是的,有支持堆栈分配和递归的 FORTRAN 77 编译器,但您可以编写一个完全符合标准的编译器,而无需堆栈分配。
因为“它有效”,所以程序员认为这是正确的方法。这也是为什么如此多的 F90+ 编译器必须添加一个选项来对变量进行零初始化(或者使所有局部变量保存,这是标准没有说的另一件事),以使旧的损坏代码继续工作。
程序员还做了许多其他无效但“有效”的事情,例如故意越界访问数组、不匹配参数类型、跳到循环中间等等。随着编译器变得更加先进,其中许多“花招”不再奏效,用户抱怨不断。我已经记不清有多少次我不得不告诉用户,不,编译器没有破坏他们的代码,它总是被破坏的。
| 归档时间: |
|
| 查看次数: |
418 次 |
| 最近记录: |