以下程序试图犯一个常见错误:修改函数参数, 而它最初作为常数传递。因此,通常存储常数 在目标代码的只读部分,并在运行时获取访问冲突。
这正是gfortran所发生的事情,优化-O0或-O1(Windows上为gfortran 4.8.1)。 但它随着-O2消失,第二个PRINT显示值100,就像第一个。
通过检查程序集输出,我可以看到在-O1情况下,函数F被优化掉了,但是计算仍然在A的代码中完成,并且存储117导致崩溃。对于-O2,不进行任何计算,结果(201)作为常量包含在汇编输出中,并且从不存储值117。
program bob
implicit none
call a(100)
contains
subroutine a(n)
integer :: n
print *, "In A:", f(n), n
print *, n
end subroutine
function f(n)
integer :: n, f
f = 2*n + 1
n = 117
end function
end program
标准是否接受此行为?这是一个错误吗? 我的第一个想法是,它可能是优化器的一个错误(它不会做一些确实有效的事情,因为修改后的值会在之后打印)。但我知道通常,标准中的未定义行为在实际运行时可能会产生任何结果。
如果我在调用中替换常量100,并且先前将变量初始化为100,则编译器会生成预期结果(第二个PRINT给出117,具有任何优化级别)。
所以,也许优化器非常聪明,在“常量”的情况下:由于代码会崩溃,因此打印不会发生,所以不需要值,所以优化了,最后程序不会崩溃。但我仍觉得有点令人费解。
答案 0 :(得分:3)
错误程序的行为符合标准要求。
该标准不要求编译器诊断此特定错误(它不违反编号的语法规则或编号约束)。除此之外,如果程序以这种方式出错,那么标准不会对Fortran处理器施加任何要求。
它没有透露编译器中的错误。任何行为都是有效的,包括编译器用棍子击败你的东西。
也许你应该说明你的意图。
答案 1 :(得分:1)
这可能是GCC优化器的常量传播模块中的一个错误。默认情况下,对于大于-O1
的任何优化级别,它都会启用,并且可以通过传递-fno-ipa-cp
来禁用。
此示例仅用于说明为每个伪参数赋予正确的INTENT
属性的重要性。在n
中将INTENT(INOUT)
标记为a
时,无论优化级别如何,编译器都会发出错误。