【问题标题】:Why Fortran Code gets Segmentation Fault?为什么 Fortran 代码会出现分段错误?
【发布时间】:2018-04-07 05:58:00
【问题描述】:

下面的 fortran 代码出现分段错误。 但是,当我将print*,pow(10_8,i) 修改为print*,pow(j,i) 时,它不会出现分段错误。为什么?这很奇怪。

module mdl
    implicit none
    integer(kind=8)::n,m=1000000007
    integer(kind=8)::p(1000),k(1000),div(10000000)
contains

    integer(kind=8) function pow(a,pwr)
        implicit none
        integer(kind=8)::a,pwr
        integer(kind=8)::cur
        cur=pwr
        pow=1
        do while(cur>0)
            if(mod(cur,2)==1)pow=mod(pow*a,m)
            a=MOD(a*a,m)
            cur=cur/2
        end do
    end function
end module



program main
    use mdl
    implicit none
    integer(kind=8)::i,j,l,r,x,y
    i=2
    j=10
    print*,pow(10_8,i)
    print*,i
end program

【问题讨论】:

  • 编译所有警告和调试信息:gfortran -Wall -gGCC 然后 use the gdb debugger
  • 使用TIO 尝试代码也会产生分段错误(使用 gfortran-7.3.1)。我尝试了一些选项,但没有有用的消息...
  • 非常感谢。我尝试了 -Wall 选项,但我无法弄清楚输出消息。对不起...。对了,给参数'a'加上value属性,就可以正常工作了。

标签: segmentation-fault fortran


【解决方案1】:

这里的问题在于函数pow 的参数a。在函数中,参数a(可能)被修改了

            a=MOD(a*a,m)

引用函数时的实际参数10_8 是一个不可修改的字面常量。这是您的程序失败的时候。当您使用print*,pow(j,i) 时,j 是一个可能被修改的变量,并且您的程序不会失败。

这里有很多复杂的事情,我不会在这个答案中完全解释(你可以搜索其他问题)。一个主题是参数关联,它解释了您为什么要尝试修改常量10_8。不过,我要说一下dummy argument intents

虚拟参数a 没有指定意图。当您打算在进入函数时使用a 的值并且您希望(可能)修改它时,适当的意图将是intent(inout)。如果你应用这个,你应该会发现你的编译器抱怨那个赋值行。

没有意图,例如在问题的情况下,是可以接受的。这有certain meaning。即a是否可以修改取决于引用函数时的实际参数是否可以。当实际参数是10_8 时,它可能不是;当它是j 时,它可能会。

关键在于,检查程序是否在此处执行了不应该执行的操作,这不是编译器的责任,而是您的责任。

现在,即使允许,您也可能不想修改实际参数 j。您有两种选择:

  • 您可以制作一个临时的本地副本(并将a标记为intent(in)),可以安全修改;
  • 您可以使用value 属性制作输入数据的匿名可修改副本。

您首先使用cur=pwr 执行此操作。以第二种为例:

integer(kind=bigint) function pow(a,pwr)
    implicit none
    integer(kind=bigint), value :: a, pwr
    pow=1
    do while(cur>0)
        if(mod(pwr,2)==1)pow=mod(pow*a,m)
        a=MOD(a*a,m)
        pwr=pwr/2
    end do
end function

您现在甚至可以将 pow 标记为纯函数。

最后,如果使用value 属性,则需要在引用函数时提供显式接口。对于函数的模块,这里就是这种情况,但在更一般的情况下需要考虑。

【讨论】:

  • 感谢您提供非常有帮助的详细解释。! !!我完全明白了。
猜你喜欢
  • 2010-10-19
  • 1970-01-01
  • 2021-07-30
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多