为何Fortran代码调用pow(10_8,i)时出现Segmentation Fault?
为什么Fortran代码中调用
pow(10_8,i)会触发Segmentation Fault? 这个问题的核心是Fortran参数传递规则+未定义行为导致的,咱们掰开揉碎了说:
先看你的
pow函数的参数问题:
你的pow函数里,参数a被直接修改了(a=MOD(a*a,m)这行),但你没有给参数声明intent(in)。Fortran默认参数传递是传引用,而且如果没指定intent,编译器会默认允许修改参数(相当于intent(inout))。当你调用
pow(10_8,i)时:10_8是一个字面量常量,编译器通常会把这类常量放在只读内存区域里。当函数通过传引用拿到这个常量的地址后,试图执行a=MOD(a*a,m)——这相当于往只读内存里写数据,直接触发内存访问权限错误,也就是你看到的Segmentation Fault。换成
pow(j,i)就正常的原因:j是一个普通变量,它的内存是可写的。虽然函数里修改a其实会偷偷修改j的值(这可能是你没注意到的潜在bug!),但至少内存是允许写入的,所以不会触发崩溃。
修复方案
想要彻底解决这个问题,有两个简单的办法:
- 给
pow函数的参数加上intent(in)声明,明确告诉编译器这两个参数是只读输入,同时把参数复制到局部变量再操作:
integer(kind=8) function pow(a,pwr) implicit none integer(kind=8), intent(in)::a,pwr ! 明确标记为输入参数 integer(kind=8)::cur, a_local a_local = a ! 复制到局部变量,避免修改原参数 pow=1 do while(cur>0) if(mod(cur,2)==1)pow=mod(pow*a_local,m) a_local=MOD(a_local*a_local,m) cur=cur/2 end do end function
- 如果不想加
intent,也可以直接在函数内部把参数a复制到局部变量,只修改局部变量,这样既不会影响外部实参,也能避免常量传入的问题。
内容的提问来源于stack exchange,提问作者Koreyuki
相关产品推荐
相关产品推荐

