2

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

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

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

4

2 回答 2

3

错误程序的行为与标准要求的一致。

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

它不会揭示编译器中的错误。任何行为都是有效的,包括编译器用棍子打你的头。

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

于 2013-09-19T14:06:27.447 回答
1

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

此示例仅用于说明为每个虚拟参数提供正确INTENT属性的重要性。当n标记为INTENT(INOUT)ina时,无论优化级别如何,编译器都会出错。

于 2013-09-19T14:34:37.023 回答