Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Debug error in fortran for the array negtivel index

Tags:

fortran95

I have a test program here:

  program test  
  implicit none  

  integer(4) :: indp  
  integer(4) :: t1(80)  

  indp = -3  
  t1(indp) = 1  
  write(*,*) t1(indp)  

  end program test

in line 8 it is wrong, because the indp is negative number. but when I compile it use 'ifort' or 'gfortran' both of them cannot find this error. and even use valgrind to debug this program it also cannot find this error. do you have any idea find this kind of problem?

like image 867
Shanshan Avatar asked Jan 28 '12 21:01

Shanshan


1 Answers

Fortran compilers aren't required to give you warnings about things like this; and in general, t1(-3) = 1 could be a perfectly reasonable statement if you set the lower bound of your fortran array to something equal to or less than -3, eg

integer(kind=4), dimension(-5:74) :: t1(80)

would certainly allow setting and reading t1(-3).

If you want to make sure these sorts of errors are checked at runtime, you can compile with -fbounds-check with gfortran:

$ gfortran -o foo foo.f90 -fcheck=bounds
$ ./foo 
At line 8 of file foo.f90
Fortran runtime error: Array reference out of bounds for array 't1', lower bound of dimension 1 exceeded (-3 < 1)

or -check bounds in ifort:

ifort -o foo foo.f90 -check bounds

$ ifort -o foo foo.f90 -check bounds
$ ./foo
forrtl: severe (408): fort: (3): Subscript #1 of the array T1 has value -3 which is less than the lower bound of 1

Image              PC                Routine            Line        Source             
foo                000000000046A8DA  Unknown               Unknown  Unknown

The reason valgrind doesn't catch this is a little subtle, but note that it would if the array were allocated:

  program test  
  implicit none  

  integer(kind=4) :: indp  
  integer(kind=4), allocatable :: t1(:)  

  indp = -3  
  allocate(t1(80))
  t1(indp) = 1  
  write(*,*) t1(indp)  
  deallocate(t1)

  end program test

$ gfortran -o foo foo.f90 -g
$ valgrind ./foo
==18904== Memcheck, a memory error detector
==18904== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==18904== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==18904== Command: ./foo
==18904== 
==18904== Invalid write of size 4
==18904==    at 0x400931: MAIN__ (foo.f90:9)
==18904==    by 0x400A52: main (foo.f90:13)
==18904==  Address 0x5bb3420 is 16 bytes before a block of size 320 alloc'd
==18904==    at 0x4C264B2: malloc (vg_replace_malloc.c:236)
==18904==    by 0x400904: MAIN__ (foo.f90:8)
==18904==    by 0x400A52: main (foo.f90:13)
==18904== 
==18904== Invalid read of size 4
==18904==    at 0x4F07368: extract_int (write.c:450)
==18904==    by 0x4F08171: write_integer (write.c:1260)
==18904==    by 0x4F0BBAE: _gfortrani_list_formatted_write (write.c:1553)
==18904==    by 0x40099F: MAIN__ (foo.f90:10)
==18904==    by 0x400A52: main (foo.f90:13)
==18904==  Address 0x5bb3420 is 16 bytes before a block of size 320 alloc'd
==18904==    at 0x4C264B2: malloc (vg_replace_malloc.c:236)
==18904==    by 0x400904: MAIN__ (foo.f90:8)
==18904==    by 0x400A52: main (foo.f90:13)
like image 156
Jonathan Dursi Avatar answered Sep 30 '22 06:09

Jonathan Dursi