4

I've inherited both the source code and a compiled executable for a Fortran77 program. I do not know what compiler was used to make the existing executable, however I'm using GCC 4.9.2. Among other things, the program reads and writes records from/to a binary file. The number of records is also stored in the beginning of the file.

My problem is that the executable I compile myself incorrectly reads the number of records from the file, and consequently throws an error when it tries to read past the last record. The binary data file was generated using the existing executable (the one I inherited), and surprisingly, when I use the existing executable to read from the data file, it works as expected.

My question is, could the Fortran READ/WRITE statements have different semantics (such as file layout) depending on the platform, fortran version, or compiler type/version?

For what it's worth, the read and write code is

    WRITE(INLIB,REC=1)NPROD,(ELMNTS(K),K=1,ITE),(ATOMWT(KK),KK=1,
 +  ITE),IOUT,INFILE,ITERM,IBM,LINEPR

    READ(INLIB,REC=1)NPROD,(ELMNTS(K),K=1,ITE),(ATOMWT(KK),KK=1,ITE)
 +  ,IOUT,INFILE,ITERM,IBM,LINEPR

NPROD is the number of records in the file. When I put a break point after the READ statement, I can see that NPROD is about 300,000, when I know for a fact that there are only about 2,000 records.

This is the code for opening the file:

    OPEN(UNIT=INLIB,FILE='PRODUCT.BIN',ACCESS='DIRECT',RECL=1188,
 +  STATUS='OLD')

With regard to endianess, I think my current platform is compatible with the binary data file because if I open it in a hex editor, I can see some legible ASCII text that makes sense in the context of the program.

Carlton
  • 4,217
  • 2
  • 24
  • 40
  • 1
    There's nothing distinct between F77 and F90, but there's the whole thing about variation between systems as a whole. See, for example, [a recent example](https://stackoverflow.com/q/32686720). – francescalus Sep 24 '15 at 12:25
  • Please show us, how the file is opened, I would suspect a wrong recl there. See for example: http://stackoverflow.com/q/32686720/577108 – haraldkl Sep 24 '15 at 12:34
  • @haraldkl I added the line for opening the file. The record length is hard-coded in there, as you can see. I don't really know how that number is determined. – Carlton Sep 24 '15 at 12:55
  • 1
    Use `inquire(iolength=reclen) nprod, elmnts(1:ite), atomwt(1:ite),iout,infile,iterm,ibm,linepr` to find the actual record length, and then use `recl=reclen` instead in your opening. See the exhaustive answer by @casey http://stackoverflow.com/a/32687019/577108. – haraldkl Sep 24 '15 at 12:59
  • The record length returned by `inquire` is certainly different than the integer literal in the code, however the call to `READ` still returns the same (incorrect) number of records. I'll read up on casey's answer. Thanks for your help. – Carlton Sep 24 '15 at 13:07
  • In that case: How are the variables defined, are you sure, the have the same kind and type definition in both settings? – haraldkl Sep 24 '15 at 13:24
  • I haven't changed the type of any variable in the original source. It's possible that the source code could have been modified after the executable was compiled, but I have no way of determining that. – Carlton Sep 24 '15 at 13:29
  • I'd suggest trying to diagnose what compiler was used on the original as a first step. See http://stackoverflow.com/questions/4554510/how-to-determine-which-compiler-has-been-used-to-compile-an-executable – Silasvb Sep 24 '15 at 14:01
  • Regarding endianess, the fact you can read some ASCII doesn't mean anything. You have to examine the numbers in the hex editor! Regarding record markers, they are not common, but they are permitted in direct access files. Some strange compiler might have used them for your files, but the probability is rather low. – Vladimir F Героям слава Sep 24 '15 at 14:04
  • Is there just the one read/write to `rec=1`? If so then there is *one* record, not 2000 or 300000. (I guess you might be using the word record to mean something different in some context?) – agentp Sep 24 '15 at 14:43
  • @Carlton the kind specification is compiler dependent, and if they are hard coded, they might result in actual different data. – haraldkl Sep 24 '15 at 14:44
  • 2
    whats the size of the file (Should be an *exact* multiple of 1188 bytes) – agentp Sep 24 '15 at 14:47
  • To answer some questions: the executable I have was compiled with Lahey Fortran, though I was under the impression that Lahey uses gfortran under the hood anyway. @agentp, I'm not actually sure what "record" means in the context of a fortran `READ` statement; I was using it in a less-formal context. Essentially, there are about 2,000 chemical species that should be present in the data file, with molecular weight and various other info for each. I was referring to each of those species as a "record". Also, the file size is *not* a multiple of the record length in the code. Hmmmm. – Carlton Sep 24 '15 at 15:25
  • 1
    A fortran record is the entirety of the "stuff" on a single read/write statement. (so 2000 records means you have 2000 read's, with `rec=1, rec=2, ..`) For fun the record is null padded to the `recl`, so the size of all the variables combined is less than or equal to the value of `recl`. Including the declarations for all those variables (and the value of `ITE`) in the question might be useful. – agentp Sep 24 '15 at 16:01
  • 1
    I solved the problem. Firstly, the file size *is* a multiple of 1188 bytes, I just read the file size wrong the first time. Secondly, there is a garbage record at the beginning of the data file; when I force the program to start reading at the second record, it works as expected. Apparently the source code I have was not the same code used to create the data file in the first place. Thank you everyone. I learned quite a bit about fortran file I/O today. – Carlton Sep 24 '15 at 18:27
  • One additional note, there is a significant amount of padding in each record, which is why the value returned by `inquire(iolength=reclen) nprod, elmnts(1:ite), atomwt(1:ite),iout,infile,iterm,ibm,linepr` is so far off from the value 1188 that is hard-coded in the source. – Carlton Sep 24 '15 at 18:29

0 Answers0