Fortran中的接口

时间:2014-07-22 14:42:14

标签: interface fortran

我在调试一些代码时偶然发现了接口的一个特殊问题,其中一个被调用的子程序有一个等级为2的伪参数但是一个实际的等级为1.参数的结果差异导致读取无效。

为了重现我创建了一个小程序(暂时忽略评论! <>):

PROGRAM ptest
USE mtest                                  ! <>
IMPLICIT NONE

REAL, ALLOCATABLE, DIMENSION(:) :: field
INTEGER :: n
REAL :: s

n = 10
ALLOCATE(field(n))
CALL RANDOM_NUMBER(field)

CALL stest(n, field, s)

WRITE(*,*) s

DEALLOCATE(field)
END PROGRAM

和一个模块

MODULE mtest                               ! <>
IMPLICIT NONE                              ! <>

CONTAINS                                   ! <>

    SUBROUTINE stest(n, field, erg)
        INTEGER :: n
        REAL, DIMENSION(n,n) :: field
        REAL :: erg

        erg = SUM(field)
    END SUBROUTINE
END MODULE                                 ! <>

据我了解,这个子程序将自动(显式?)接口放置在模块中。问题是,实际field的长度为10,而子例程将长度为10x10=100的字段与valgrind中的! <>字段清晰可见,作为无效读取。

然后我在没有模块的情况下测试了相同的代码,即标有-Wimplicit-interface的所有行都被删除/评论。结果,gfortran的INTERFACE stest MODULE PROCEDURE stest END INTERFACE 发出警告,但代码像以前一样工作。

所以我的问题是:处理这种情况的最佳方法是什么?我是否应该始终放置通用接口

REAL, ALLOCATABLE, DIMENSION(:,:) :: field

在模块中?或者我应该用延迟形状数组替换字段的定义(即stest)?

编辑:为了更准确地说明我的问题,我不想解决这个特殊问题,但想知道,该怎么做才能从编译器获得更好的诊断输出。

E.g。给定的代码不会给出错误消息,并且原则上会产生分段错误(但代码不会注意到它)。放置一个通用接口会产生至少一个错误,抱怨,找不到{{1}}的匹配定义,这也没有用,特别是在没有源代码的情况下。只有延迟形状的数组才会产生可理解的错误消息(排名不匹配)。

这就是,我想知道为什么自动模块接口没有给出类似的警告/错误信息。

1 个答案:

答案 0 :(得分:1)

编译器无法警告您,因为代码是合法的!您只是传递了错误的n和非正方形的点数。对于显式形状数组,您负责正确的尺寸。考虑

ALLOCATE(field(1000))

CALL stest(10, field, s)

虽然实际和伪参数的元素数量不同,但此代码仍然有效。也许建议gfortran开发人员检查伪参数是否不大,但我不确定它有多难。

通用接口使编译器检查TKR规则。不允许不同等级的数组的序列关联,并且编译将失败。因此,它将禁用将不同等级的数组传递给显式形状和假定大小的伪参数的所有合法用途,并限制您的可能性。

解决方案是什么?将显式形状数组用于它们适合的情况,否则使用假定的形状数组(可能具有contiguous属性)。通用接口也可能有所帮助,但会改变语义并限制可能的使用。