5

I'm trying to read some data from a file, and the endfile record detection is important to stop reading. However, depending of the array dimensions of the array used to read data, I cannot detect properly the endfile record and my Fortran program stops.

The program is below:

!integer, dimension(3) :: x                      ! line 1.1
!integer, dimension(3,10) :: x                   ! line 1.2
integer, dimension(10,3) ::                      ! line 1.3
integer :: status,i=1
character(len=100) :: error

open( 30, file='data.dat', status='old' )
do
  print *,i
  !read( 30, *, iostat=status, iomsg=error ) x          ! line 2.1
  !read( 30, *, iostat=status, iomsg=error ) x(:,i)     ! line 2.2
  read( 30, *, iostat=status, iomsg=error ) x(i,:)      ! line 2.3

  if ( status < 0 ) then        print *,'EOF'
    print *,'total of ',i-1,' lines read.'
    exit
  else if ( status > 0 ) then
    print *,'error cod: ',status
    print *,'error message: ', error
    stop
  else if ( status == 0 ) then
    print *,'reading ok.'
    i = i + 1
  end if
end do

With 'data.dat' file been:

10 20 30
30 40 50

When lines 1.3 and 2.3 are uncommented the mentioned error appears:

error cod: 5008

error message: Read past ENDFILE record

However, using lines 1.1 and 2.1, or 1.2 and 2.2, the program works, detecting endfile record.

So, I would like some help on understanding why I cannot use lines 1.3 and 2.3 to read properly this file, since I'm giving the correct number of array elements for read command.

I'm using gfortran compiler, version 6.3.0.

EDIT: simpler example

the following produces a 5008 "Read past ENDFILE record" error:

implicit none
integer x(2,2),s
open(20,file='noexist')
read(20,*,iostat=s)x
write(*,*)s
end

if we make x a scalar or a one-d array ( any size ) we get the expected -1 EOF flag. It doesn't matter if the file actually doesn't exist or is empty. If the file contains some, but not enough, data its hard to make sense of which return value you might get.

Community
  • 1
  • 1
  • 1
    Please show output from when you run this program (working and non-working variants). It isn't clear to me why you would get a message about an end-of-file condition so the exact output will clarify. – francescalus Mar 02 '18 at 17:41
  • You don't have an 'x' in line 1.3. Is this just a transcribing error? – Ross Mar 02 '18 at 18:11
  • Interesting. I'm able to replicate the issue with gfortran 4.8 but not ifort 16.0. I agree it's a problem. – Ross Mar 02 '18 at 18:16
  • gfortran 7.2 has the same problem. – Ross Mar 02 '18 at 18:18
  • confirmed, (gfortran 4.8.5). I edited the question to show the actual message I get. this is clearly a gfortran bug. You can workaround simply by making your first test `status < 0 .or. status == 5008` – agentp Mar 02 '18 at 20:24
  • After a bit of investigating , gfortran seems to only throw an actual EOF (status=-1) when attempting to read a single scalar item. The "past end" error is thrown when it hits EOF while reading an array. – agentp Mar 02 '18 at 20:39

2 Answers2

-1

I am not sure if I am expressing myself correctly but it has to do with the way fortran is reading and storing 2d-arrays. When you are using this notation: x(:,i), the column i is virtually expanded in-line and the items are read using this one line of code. In the other case where x(i,:) is used, the row i is read as if you called read multiple times. You may use implied loops if you want to stick with a specific shape and size. For example you could use something like that:read( 30, *, iostat=status, iomsg=error ) (x(i,j), j=1,3)

In any case you should check that your data are stored properly (as expected at least) in variable x.

francescalus
  • 24,364
  • 10
  • 50
  • 78
Aristotelis
  • 131
  • 3
  • 9
  • 1
    Why do you expect `(x(i,j),j=1,3)` to be different from `x(i,1:3)`? And why is using `x(i,:)` like using multiple read statements? – francescalus Mar 02 '18 at 17:43
  • I don't think this answers the question. – Ross Mar 02 '18 at 18:32
  • @francescalus I agree that it should not be different, but it has happened to me before. Some compilers exhibited the behaviour I described. – Aristotelis Mar 02 '18 at 20:40
-1

Please note this is only a guess. Remember that Fortran stores arrays in column major order. When gfortran compiles read() x(:,i), the 3 memory locations are next to each other so in the executable, it produces a single call to the operating system to read in 3 values from the file.

Now when read() x(i,:) is compiled, the three data elements x(i,1), x(i,2) and x(i,3) are not in contiguous memory. So I am guessing the executable actually has 3 read calls to the operating system. The first one would trap the EOF but the 2nd one gives you the read past end of file error.

UPDATE: I have confirmed that this does not occur with Intel's ifort. gfortran seems to have had a similar problem before: Bad IOSTAT values when readings NAMELISTs past EOF. Whether this is a bug or not is debatable. The code certainly looks like it should trap an EOF.

Dan Sp.
  • 1,268
  • 1
  • 11
  • 21