Fortran函数中未声明save属性的变量为何能在调用间保留值?
Fortran函数中未声明save属性的变量为何能在调用间保留值?
这个问题问到点子上了——这完全是Fortran标准的「未定义行为」碰上了Intel IFORT编译器的实现细节,刚好凑出了看似正常的效果,咱们一步步拆解:
首先先明确Fortran标准的规定:对于函数内部声明的、既没有save属性,也没有在声明时初始化的局部变量,标准不保证它在函数调用之间会保留值。这种情况属于「未定义行为」——理论上每次调用函数时,这个变量的值可能是随机的,完全看编译器的具体实现。
那为什么你的代码里previous_bar能一直保留上一次的值呢?这得说Intel IFORT的具体实现逻辑:
- 大型派生类型的存储优化:你提到
my_type是个大型数据结构,IFORT对于这类体积较大的局部变量,通常不会把它放到栈内存里(栈空间有限,大变量很容易导致栈溢出),而是会把它分配到静态存储区——这个区域的内存和全局变量类似,函数退出后不会被释放或重置,所以下一次调用函数时,变量还能保持之前的值。这是编译器为了避免栈溢出做的实用优化,但绝对不是Fortran标准要求的行为。 - 关于
private属性的误区:你怀疑private属性有关系?其实完全没关系!private只是控制模块内的实体能不能被外部访问,和变量的存储方式、是否保留值没有半毛钱关系,这个猜测可以排除啦。
另外你提到第一次调用时previous_bar是零初始化的(字符为空格、数值为0),这也是IFORT的默认行为——静态存储区的未初始化变量会被默认清零,但同样不是标准强制的,换个编译器(比如GFortran)可能就会给你随机值。
最后给个关键建议:
既然这是依赖编译器实现的未定义行为,哪天编译器升级、或者换成其他编译器,这段代码大概率会出问题。最稳妥的修复方式是显式给previous_bar加上save属性,或者在声明时初始化(比如type(my_type) :: previous_bar = my_type(),这种初始化会自动隐含save属性),让代码的行为完全符合Fortran标准,不再靠「运气」运行。
备注:内容来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

