【问题标题】:Interfaces in FortranFortran 中的接口
【发布时间】:2014-07-22 14:42:14
【问题描述】:

我在调试一些代码时偶然发现了一个与接口有关的特定问题,其中被调用的子例程有一个 2 级的虚拟参数,但有一个 1 级的实际参数。由此产生的参数差异导致读取无效。

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

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 中作为无效读取清晰可见。

然后我在没有模块的情况下测试了相同的代码,即所有标有! &lt;&gt; 的行都被删除/注释了。结果,gfortran 的-Wimplicit-interface 抛出了一个警告,但是代码和以前一样工作。

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

INTERFACE stest
    MODULE PROCEDURE stest
END INTERFACE

在模块中?还是应该用延迟形状的数组(即REAL, ALLOCATABLE, DIMENSION(:,:) :: field)替换字段的定义?

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

例如给定的代码不会给出错误消息,并且原则上会产生分段错误(尽管代码没有注意到它)。放置一个通用接口至少会产生一个错误,抱怨没有找到stest 的匹配定义,这也不是很有帮助,尤其是在你没有源代码的情况下。只有延迟形状的数组会导致可以理解的错误消息(排名不匹配)。

如果我想知道,这就是为什么自动模块界面没有给出类似的警告/错误消息。

【问题讨论】:

  • 最简单的解决方案是在主程序中将字段声明为二阶数组。 (即REAL, ALLOCATABLE, DIMENSION(:,:) :: field。)并将其分配给子例程中使用的大小。那么实际和虚拟参数是一致的。您是否有不想这样做的理由?
  • 也可以通过field(1)获取“序列关联”。
  • 可以使用序列关联,但元素不匹配的数量也必须固定。 rank-1 100 个元素可以匹配 rank-2 10x10。

标签: interface fortran


【解决方案1】:

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

ALLOCATE(field(1000))

CALL stest(10, field, s)

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

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

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

【讨论】:

  • 感谢您的澄清。现在,我必须告诉我的同事,谁产生了这个代码,将来要做什么......我并没有真正考虑过这样一个事实,它可能是完全有效的代码,因为例如通用接口确实抱怨。
猜你喜欢
  • 2014-07-12
  • 2013-05-05
  • 2013-09-20
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多