为什么Fortran代码会出现分段错误? [英] Why Fortran Code gets Segmentation Fault?

查看:91
本文介绍了为什么Fortran代码会出现分段错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The fortran code below gets segmentation faults. However, when I modify print*,pow(10_8,i) to print*,pow(j,i), it works without vomiting segmentation fault. Why? This is very weird.

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

推荐答案

这里的问题出在函数 pow 的自变量 a 上.在函数中,参数 a (可能)在行上被修改了

The problem here is with the argument a of the function pow. In the function the argument a is (potentially) modified on the line

            a=MOD(a*a,m)

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

The actual argument 10_8 when referencing the function is a literal constant which may not be modified. This is when your program fails. When you use print*,pow(j,i) the j is a variable which may be modified, and your program doesn't fail.

这里发生了很多复杂的事情,在这个答案中我不会完全解释(您可以搜索有关此问题的其他信息).一个主题是 argument association (参数关联),该主题解释了为什么要尝试修改常量 10_8 .但是,我会说一些关于虚拟参数意图.

There is a lot of complicated stuff going on here, that I won't fully explain in this answer (you can search for other questions for that). One topic is argument association which explains why you are trying to modify the constant 10_8. However, I'll say something about dummy argument intents.

伪参数 a 没有指定意图.当您打算使用 a 的值进入函数时,并且希望(可能)对其进行修改时,适当的意图应为 intent(inout).如果应用此方法,则应该发现编译器抱怨该分配行.

The dummy argument a has no intent specified. As you intend to use the value of the a as it enters the function and you wish to (potentially) modify it an appropriate intent would be intent(inout). If you apply this, you should find your compiler complain about that assignment line.

没有问题的意图是可以接受的.这具有某些含义.也就是说,是否可以修改 a 取决于在引用该函数时实际的参数是否可以修改.当实际的参数是 10_8 时,它可能不是.当它是 j 时.

Having no intent, such as in the case of the question, is an acceptible thing. This has certain meaning. That is, whether a may be modified depends on whether the actual argument when referencing the function may. When the actual argument is 10_8 it may not; when it is j it may.

至关重要的是,检查程序是否在此处应做的事情不是编译器的责任,而是您的责任.

The crucial thing is that it isn't the compiler's responsibility, but yours, to check whether the program is doing something here it shouldn't.

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

Now, you may not want to modify the actual argument j even when you are allowed to. You have a couple of options:

  • 您可以制作一个临时的本地副本(并将 a 标记为 intent(in)),可以安全地对其进行修改;
  • 您可以使用 value 属性为输入数据创建匿名可修改的副本.
  • you can make a temporary local copy (and mark a as intent(in)), which may be safely modified;
  • you can make an anonymous modifiable copy of the input data using the value attribute.

您首先使用 cur = pwr 进行此操作.作为第二个示例:

You do this first with cur=pwr. As an example of the second:

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 标记为纯函数.

You now may even mark pow as a pure function.

最后,如果使用 value 属性,则在引用该函数时要求显式接口可用.使用此功能的模块就是这种情况,但是在更一般的情况下需要考虑这一点.

Finally, if using the value attribute it is required that an explicit interface be available when referencing the function. With the module for the function this is the case here, but this is something to consider in more general cases.

这篇关于为什么Fortran代码会出现分段错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆