gfortran优化器可防止访问冲突

时间:2013-09-19 12:20:02

标签: fortran gfortran

以下程序试图犯一个常见错误:修改函数参数, 而它最初作为常数传递。因此,通常存储常数 在目标代码的只读部分,并在运行时获取访问冲突。

这正是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,具有任何优化级别)。

所以,也许优化器非常聪明,在“常量”的情况下:由于代码会崩溃,因此打印不会发生,所以不需要值,所以优化了,最后程序不会崩溃。但我仍觉得有点令人费解。

2 个答案:

答案 0 :(得分:3)

错误程序的行为符合标准要求。

该标准不要求编译器诊断此特定错误(它不违反编号的语法规则或编号约束)。除此之外,如果程序以这种方式出错,那么标准不会对Fortran处理器施加任何要求。

它没有透露编译器中的错误。任何行为都是有效的,包括编译器用棍子击败你的东西。

也许你应该说明你的意图。

答案 1 :(得分:1)

这可能是GCC优化器的常量传播模块中的一个错误。默认情况下,对于大于-O1的任何优化级别,它都会启用,并且可以通过传递-fno-ipa-cp来禁用。

此示例仅用于说明为每个伪参数赋予正确的INTENT属性的重要性。在n中将INTENT(INOUT)标记为a时,无论优化级别如何,编译器都会发出错误。