问题
I am linking some fortran code (f90) from matlab using mex and I am having matlab freeze occasionally.
In the past, I had freezing happening due to mismatch between data types (say integer*4 vs integer*8).
The code I am linking has many implicitly defined variables, so I am wondering if there is a hidden data type conflict that only occurs occasionally.
To rule out data type mismatch as the cause of the freeze, I would like to have the compiler requiring all variables to be explicitly declared.
Questions:
How do I get gfortran to require all variables to be explicitly declared at compile time? Failing that, is there any way to at least get warnings?
Is a "real" data type interpreted by gfortran as a specific kind in all architectures? If so, which one is it (real*4, real*8, ...)?
Is there anyway to force gfortran to interpret the "real" data type as a specific kind, say "real*4"?
Any ideas on what makes the fortran code to freeze when called from a mex compiled routine in matlab (other than data type mismatches)?
Thanks for any help.
Until I figure this out I will be going through many lines of codes trying to list all implicitly defined variables. Needless to say, I will be tremendously grateful to anyone who frees me from such a boring task...
Best,
G.
回答1:
- You can require all variables to be explicitly declared by adding
implicit none
. - I believe the default "real" data type is a
real*4
. - You can use a command-line flag
-fdefault-real-8
to force all variables declared asreal
to be interpreted as areal*8
Note (for writing more code, not necessarily trying to solve the current bug):
If you're using Fortran 90 code, you can use real(kind=4)
or real(kind=8)
with gfortran rather than the real*4
or real*8
syntaxes. I've moved away from setting the real or integer size using command-line flags and instead use an integer, parameter :: REAL_SIZE
variable to hold the appropriate number (I typically go for 4 or 8 because all the compilers I use support them, but if you want to be very portable you should use the selected_real_kind
routine)
回答2:
As already stated, in your source code, you can use implicit none. The advantage is that this is portable to all compilers.
With gfortran, you can use the compiler option -fimplicit-none. This advantage is that this will catch variables that you forgot to explicitly type even if you forgot to include implicit none. Most other compilers have a similar option.
Both are highly recommended -- implicit typing is pernicious, and allows the mistake of typos creating unintended variables.
What a plain "real" means is up to the compiler -- if you have specific requirements, it is best to use a more specific declaration. The best way is to define a parameter with the selected real kind intrinsic and use that -- for a similar discussion see Fortran: integer*4 vs integer(4) vs integer(kind=4)
回答3:
IMPLICIT NONE
and compiler option already mentioned.
Let's talk about floating point arithmetic. The problem is that (ss mentioned here) MATLAB constructs both the double-precision (or double) and the single-precision (or single) data types according to IEEE® Standard 754 but Fortran standard doesn't require it's default and double precision real's to conform this standard. As you can see the standard document even use another name (default real, not single-precision).
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
Here in the first two strings of my kinds specification I've used convenient way to obtain kinds for default real and double precision real. The next two kinds correspond to mentioned IEEE standard.
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
The output on my machine (Mac OS X 10.6, gfortran 4.5.1) is:
8 15 307
8 15 307
4 6 37
8 15 307
So Fortran's default real kind is not equal to IEEE standard single-precision float kind.
So it might be the source of bugs. The precision is lost somewhere, some variable becomes equal to 0.0 instead of being slightly bigger/smaller the 0.0 and then you divide by this value (which is exactly 0.0). Well, it can freeze the program.
回答4:
One of these works with most compilers, since Fortran 77:
implicit none
or
implicit undefined(a-z)
Real
is architecture dependent; the default size is usually modifiable by a command line option.
I don't have any experience linking with Matlab.
来源:https://stackoverflow.com/questions/3559919/force-explicit-variable-declaration-with-gfortran