You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fortran中将函数名作为参数传递时数组入参失效的问题排查与解决

异常产生的核心原因

问题根源来自过程调用时接口不匹配:

  • 在call_test子例程里通过double precision,external::fn声明形参fn时,并没有给编译器提供fn的完整接口信息,编译器仅知道这是一个返回双精度标量的外部过程,完全不知道它的入参是数组、还是标量、数组的形状约定是什么。
  • 实际传入的ga函数,入参x是假定形状的显式接口数组(声明为double precision,dimension(0:) :: x),这类数组的传递需要附带专门的数组描述符(记录数组秩、各维上下界、起始地址等信息)。按照Fortran语言规则,假定形状数组作为过程入参时,必须为被调过程提供显式接口才能正确传递参数。
  • 当你用无接口的external声明调用ga时,编译器按照老式的隐式接口规则,直接把数组的首地址作为入参传递,完全没有传递ga需要的数组描述符:
    • 对ifort来说,ga内部读取size(x)时,会把栈上的随机内存值当成数组长度,最终访问非法内存触发段错误;
    • 对gfortran来说,会因为参数不匹配默认构造一个空的数组对象,导致数组长度为0、求和结果为0的错误表现。
  • 你之前测试标量入参时能正常运行,是因为标量的隐式传递规则刚好和接口约定对齐,没有触发参数传递的错位问题。

可运行的代码修改方案

修改思路是放弃无接口的external声明,通过抽象接口块给call_test的函数形参定义明确的签名,匹配实际传入的ga的接口要求,修改后的完整可运行代码如下:

module fun
    implicit none
    private
    public    ::  ga, call_test

    ! 新增:定义匹配要求的抽象函数接口
    abstract interface
        function scalar_return_vecfun(x) result(res)
            double precision, intent(in) :: x(:)
            double precision :: res
        end function scalar_return_vecfun
    end interface

contains

    subroutine call_test(fn)
        ! 修改:用procedure指定接口类型,替换原来的external声明
        procedure(scalar_return_vecfun) :: fn
        double precision :: f
        double precision, dimension(0:2) :: x0

        x0 = 0.111d0
        print*,'Input x0=',x0
        print*,'sze x0:',size(x0)

        f = fn(x0)
        print*,'fn(x0)=',f

    end subroutine call_test


    function ga(x) result(f)
        double precision, dimension(0:) :: x
        double precision :: f

        print*,'size x inside ga:',size(x)
        print*,'x in ga is:=',x

        f = sum(x)
    end function ga

end module


program main
    use fun
    call call_test(ga)
end program main

修改后不管是ifort还是gfortran编译运行,都会得到正确的执行结果:

Input x0=  0.111000000000000       0.111000000000000       0.111000000000000
 sze x0:                     3
 size x inside ga:           3
 x in ga is:=  0.111000000000000       0.111000000000000       0.111000000000000
 fn(x0)=   0.333000000000000

补充说明:如果后续需要同时适配标量入参、不同秩数组入参的函数传入,可以在抽象接口块中新增重载的函数签名,通过过程泛化的方式匹配不同的调用场景,不需要再回到老式的无接口external写法。

内容的提问来源于stack exchange,提问作者Kiyomine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.28 05:06:09