强制显式变量声明与gfortran
我正在使用mex链接一些fortran代码(f90)从matlab,我偶尔有matlab冻结。强制显式变量声明与gfortran
过去,由于数据类型不匹配(例如整数* 4与整数* 8),我发生了冻结。
我连接的代码有许多隐式定义的变量,所以我想知道是否有偶尔出现的隐藏数据类型冲突。
要排除数据类型不匹配的原因冻结,我希望编译器要求显式声明所有变量。
问题:
我怎么gfortran需要在编译时明确声明的所有变量?如果没有,有没有办法至少得到警告?
gfortran是否将“真实”数据类型解释为所有体系结构中的特定种类?如果是这样,哪一个(真实* 4,真实* 8,...)?
有没有办法强迫gfortran将“真实”数据类型解释为特定类型,比如说“真实* 4”?
有什么想法让fortran代码在从matlab中的mex编译例程中调用时冻结(数据类型不匹配除外)?
感谢您的任何帮助。
直到我明白了这一点,我会经历许多代码行,试图列出所有隐式定义的变量。 不用说,我将大大感激的人谁解放了我从这么无聊的任务......
最佳,
G.
- 您可以要求通过添加
implicit none
明确声明所有变量。 - 我相信默认的“真实”数据类型是
real*4
。 - 您可以使用命令行标志,
-fdefault-real-8
迫使声明为real
所有变量被解释为real*8
注(写更多的代码,不一定试图解决当前的bug): 如果您正在使用Fortran 90代码,可以使用real(kind=4)
或real(kind=8)
与gfortran,而不是real*4
或real*8
语法。我已经不再使用命令行标志设置实数或整数大小,而是使用一个integer, parameter :: REAL_SIZE
变量来保存适当的数字(我通常选择4或8,因为我使用的所有编译器都支持它们,但是如果您想要非常便携,您应该使用selected_real_kind
例程)
其中一个适用于大多数编译器,因为Fortran 77的:
implicit none
或
implicit undefined(a-z)
Real
是架构相关的;默认大小通常可以通过命令行选项进行修改。
我没有任何与Matlab连接的经验。
感谢您的快速回复。 – gvrocha 2010-08-24 19:40:28
如前所述,在您的源代码中,您可以使用隐式无。优点是这对所有编译器都是可移植的。
使用gfortran,您可以使用编译器选项-fimplicit-none。这个好处是,它会捕获你忘记明确键入的变量,即使你忘记了包含隐含的没有。其他大多数编译器都有类似的选项。
这两个都是强烈推荐 - 隐式类型是有害的,并允许错字错误创建意想不到的变量。
简单的“真实”意味着什么取决于编译器 - 如果您有特定要求,最好使用更具体的声明。最好的方法是用选定的真实类型内在定义一个参数并使用它 - 对于类似的讨论,请参见Fortran: integer*4 vs integer(4) vs integer(kind=4)
IMPLICIT NONE
和编译器选项已经提到。
让我们来谈谈浮点运算。问题在于(MATLAB提到的here)MATLAB根据IEEE® Standard 754构造了双精度(或双精度)和单精度(或单精度)数据类型,但Fortran标准并不要求它是默认的,双精度实数来符合这个标准。正如您可以看到标准文档甚至使用其他名称(默认为真,而不是单精度)。
MODULE kinds
IMPLICIT NONE
INTEGER, PARAMETER :: fortran_default = kind(0.0)
INTEGER, PARAMETER :: fortran_double = kind(0.0D0)
INTEGER, PARAMETER :: ieee_single = selected_real_kind(7, 38)
INTEGER, PARAMETER :: ieee_double = selected_real_kind(15, 307)
END MODULE kinds
在我的种规格的前两个字符串中,我用方便的方法来获得默认实数和双精度实数的种类。接下来的两种对应于提到的IEEE标准。
PROGRAM main
USE kinds
IMPLICIT NONE
REAL(kind=ieee_single) :: is
REAL(kind=ieee_double) :: id
REAL(kind=fortran_default) :: fs
REAL(kind=fortran_double) :: fd
PRINT *, kind(is), precision(is), range(is)
PRINT *, kind(id), precision(id), range(id)
PRINT *, kind(fs), precision(fs), range(fs)
PRINT *, kind(fd), precision(fd), range(fd)
END PROGRAM main
我的机器(的Mac OS X 10.6,gfortran 4.5.1)上的输出是:
8 15 307
8 15 307
4 6 37
8 15 307
所以Fortran语言的默认实样不等于IEEE标准的单精度浮点数的那种。
所以它可能是错误的来源。精度在某处丢失,某些变量等于0.0,而不是略大于0.0,然后除以该值(正好为0.0)。那么,它可以冻结该程序。
观察>>猜测 - 非常好。 – 2010-08-24 20:39:25
技术上,selected_real_kind(7,38)提供至少7位精度 - 如果编译器选择它可以提供更多精度,所以这不能保证选择IEEE类型。如果您绝对必须拥有IEEE类型,则有Fortran 2003的新IEEE模块 - 但尚未普遍支持。 – 2010-08-24 20:59:41
@ M. S. B .:您的评论完全有效。这个想法是让Fortran代码中的浮点数的精度至少达到IEEE的单精度和双精度。 – Wildcat 2010-08-25 07:38:39
非常感谢,特别是关于-fdefault-real-8标志的提示。你知道是否还有一个-fdefault-real-4标志吗?我在gfortran上尝试过,但它似乎没有工作...... – gvrocha 2010-08-24 19:40:13
我不这么认为,因为那只是默认设置。 – 2010-08-24 19:52:09
所以真正的默认值不是架构依赖呢? – gvrocha 2010-08-24 19:57:49