GFortran frequently encountered trouble
Makefile goofs
Gfortran creates a file name.mod for each module name. This confuses the gnu make, which thinks that .mod files are Modula2 source code files. You must override this built-in rule by adding the following line somewhere in your Makefile.
%.o : %.mod
Debugging with gdb
When using gdb, you face a few quirks:
- Get the newest gdb, 6.4.50 as of this writing. 6.3 is definitly too old; it has many subtle problems which 6.4 does not have.
The program does not start at the first executable line of your code, but rather at a runtime library that comes with gfortran. Use b MAIN__ to set a breakpoint at the first line of Fortran code.
Name mangling: It seems not all names are accessible in gdb. Examples are local variables, say i, which show up as innn when tab-expanding i, but if you enter p innn, an error message is generated.
Module name mangling: Subroutine Mysub in module Mymod has the name __mymod__mysub. Same is valid for functions and globals. Note the double underscores and all lower caps.
arrays passed to routines with an interface, either explicit or via use and allocatable arrays are hard to examine, because what you see in gdb is the array descriptor.
To get a backtrace at a run-time error of a library, set in gdb the break point at exit (b exit) and run the program.
Emacs
gfortran error messages do not comply to patterns in emacs's compilation-error-regexp-alist. This means you will not be able to jump in your buggy source easily. Rats.
As of 2006-11-05, gfortran trunk (4.3) should produce error messages in gnu standard format, at least for simple messages.
Block Data
Block Data can be troublesome. Having problems getting your block data to link and to initialize ?
This may be the solution: PR12074 (invalid)
Intentional Overflow
Some programs rely on the overflow of variables, e.g.
integer(4) :: temper_b data temper_b /z'EFC60000'/
This is invalid Fortran 95/2003 as the BOZ overflows the 4-byte variable; therefore gfortran gives the error Error: Arithmetic overflow converting INTEGER(16) to INTEGER(4). If this overflow is on purpose, you can use the -fno-range-check option to force gfortran to accept an overflow.
Sharing Common Blocks Between Tasks
Here is an example that demonstrates using IPC shared memory to share common blocks across fortran tasks. Note the address to which the common block is mapped is arbitrary, check to ensure that no library you link with conflicts.
[bdavis@localhost ~]$ cat a.f
IMPLICIT NONE
CHARACTER*16 S
INTEGER*4 I,STAT,KEY,SIZE,ADDR
DATA KEY / Z'FFF100??' /
DATA SIZE / Z'00001000' /
DATA ADDR / Z'40200000' /
COMMON / GLOBAL01?? / S
CALL X_INCLD(KEY,ADDR,SIZE,STAT)
IF (STAT.EQ.0) THEN
PRINT*
PRINT*
PRINT*
DO I=1,30
PRINT*,'S from shared memory is ',S
CALL SLEEP(1)
ENDDO
END IF
END
[bdavis@localhost ~]$ cat b.f
IMPLICIT NONE
CHARACTER*16 S
INTEGER*4 I,STAT,KEY,SIZE,ADDR
DATA KEY / Z'FFF100??' /
DATA SIZE / Z'00001000' /
DATA ADDR / Z'40200000' /
COMMON / GLOBAL01?? / S^M
CALL X_INCLD(KEY,ADDR,SIZE,STAT)
IF (STAT.EQ.0) THEN
DO I=1,30
WRITE(S,*)'COUNT IS ',I
CALL SLEEP(2)
ENDDO
END IF
END
[bdavis@localhost ~]$ cat shared_mem.c
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
void x_incld__ (int *key, int *addr, int *size, int *status) {
int shmid;
if ((shmid = shmget (*key, *size, IPC_CREAT | IPC_EXCL | 0666)) == -1)^M
{
shmid = shmget (*key, *size, 0);
}
*status = (int) shmat (shmid, (const void *) *addr, SHM_REMAP);
if (*status == *addr)
{
*status = 0;
}
else
{
*status = -1;
}
return;
}
[bdavis@localhost ~]$ g77 -Wall -g -o a a.f shared_mem.c -Wl,--defsym -Wl,global01_=0x40200000
[bdavis@localhost ~]$ g77 -Wall -g -o b b.f shared_mem.c -Wl,--defsym -Wl,global01_=0x40200000
[bdavis@localhost ~]$ ./a&;./b& [1] 7234 [2] 7235
[bdavis@localhost ~]$
S from shared memory is COUNT IS 1
S from shared memory is COUNT IS 1
S from shared memory is COUNT IS 2
S from shared memory is COUNT IS 2
S from shared memory is COUNT IS 3
S from shared memory is COUNT IS 3
S from shared memory is COUNT IS 4
S from shared memory is COUNT IS 4
S from shared memory is COUNT IS 5
S from shared memory is COUNT IS 5
S from shared memory is COUNT IS 6
S from shared memory is COUNT IS 6
S from shared memory is COUNT IS 7
S from shared memory is COUNT IS 7
S from shared memory is COUNT IS 8
S from shared memory is COUNT IS 8
S from shared memory is COUNT IS 9
S from shared memory is COUNT IS 9