【问题标题】:gfortran optimizer prevents an access violationgfortran 优化器防止访问冲突
【发布时间】:2013-09-24 12:37:05
【问题描述】:

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

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

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

【问题讨论】:

  • 我无法重现这个。使用 gfortran 4.6.3 和 ifort 13.1.3 时,我在 n=117 行收到带有标志 O1O2O3 的段错误
  • 对我来说结果相同。 FWIW Oracle sunf90 -fast 打印 201 117 117
  • 请注意,这可能与您使用内部过程有关。它们可能是内联的。
  • F 是内联的,而不是 A。但你是对的,当函数不是内部的时,我也总是遇到段错误。这很自然:当这些函数是内部函数时,只有主程序可以调用它们,所以编译器“知道”唯一的调用是用一个常量完成的,它可以以某种方式优化 n=117。当它们不是内部的时,程序可以与调用它们的其他函数链接,并使用真正的变量参数。
  • @Kyle。然后它在以后的版本中被引入。我正好使用 this 一个。

标签: fortran gfortran


【解决方案1】:

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

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

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

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

【讨论】:

  • 这或多或少是我所期望的答案。无论如何,编译器会根据优化级别甚至是简单的 PRINT 语句的存在而生成崩溃程序,这有点奇怪。尽管允许编译器根据标准执行此操作(我自己已经理解,我知道我可能(!)用一个糟糕的 Fortran 程序声明 WW3),这有点烦人,也许,只是也许,编译器错误。我不确定 GCC 维护者是否有意这样做。
  • 顺便说一句,我知道我应该说什么。这只是一个测试,因为我不会编写这个程序用于生产用途(或用于任何用途,除了测试)。我想知道我的编译器的局限性,也许我刚刚接触过一个。
  • 请注意,即使 a 的实际参数不是常量,您的代码也不符合标准。
  • 也许我还睡着了,我看不见。为什么不符合要求?
  • 参见 F2008 7.1.4p1 -“如果函数引用导致定义......函数的实际参数,则该参数......不应出现在同一语句的其他位置。”
【解决方案2】:

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

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

【讨论】:

  • 谢谢!这似乎是导致问题的选项,很高兴知道它来自哪里。
  • IPA-CP 似乎在许多极端情况下造成了很多麻烦。如果您查看 GCC 的 Bugzilla,第一个问题始终是“它是否适用于 -fno-ipa-cp?”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-20
  • 1970-01-01
相关资源
最近更新 更多