Shane Hart
Shane Hart

Reputation: 21

GFORTRAN_CONVERT_UNIT environment variable not working on some platforms?

I have a rather monolothic code that reads in a large variety of data from unformatted big endian binary files. Normally the code is run from within a bash script that sets the environment variable GFORTRAN_CONVERT_UNIT='native;big_endian:60-70,80-89' and then opens those big endian data files using one of those unit numbers. This works fine for Fedora and RHEL. However, when I've run the program on Debian (and derivatives including Ubuntu and Linux Mint), OpenSUSE, and Arch Linux I get the following malloc error right before the Fortran code does any execution:

malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted

To further demonstrate the problem I wrote two Fortran programs, one to write a simple big endian data file, and one to read it:

Write program:

shane@linux-0r5g:~/temp> cat test_write.f90
program test_write
implicit none

integer, parameter :: NUM = 10
integer :: i

open (unit=88,form='unformatted',convert='big_endian')
do i = 1,NUM
  write (88) i
end do

close (88)

end program test_write

Read program:

shane@linux-0r5g:~/temp> cat test_read.f90
program test_read
implicit none

integer, parameter :: NUM = 10
integer :: readInt
integer :: i

open (unit=88,form='unformatted')
do i = 1,NUM
  read (88) readInt
  write (*,*) readInt
end do

close (88)

end program test_read

Running the programs (this is on OpenSUSE 12.2 32-bit using GCC 4.7.1, but also fails with Ubuntu 32-bit):

shane@linux-0r5g:~/temp> ./test_write 
shane@linux-0r5g:~/temp> ./test_read
    16777216
At line 10 of file test_read.f90 (unit = 88, file = 'fort.88')
Fortran runtime error: End of file
shane@linux-0r5g:~/temp> GFORTRAN_CONVERT_UNIT='native;big_endian:88' ./test_read
test_read: malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Aborted
shane@linux-0r5g:~/temp> 

Obviously, the first attempt fails because it's trying to read a big endian file with little endian reads, but the second attempt should work. Indeed, it does work on many systems. Setting GFORTRAN_CONVERT_UNIT='big_endian' instead of trying to cherry pick unit numbers also works on all systems.

I don't think it's a 32-bit vs 64-bit problem as the monolithic code is on a 64-bit server, and the environment variable should work regardless... I'm running these on 32-bit now because that's what I have on my laptop.

Any ideas?

Upvotes: 1

Views: 382

Answers (1)

user4490638
user4490638

Reputation:

This issue was due to a bug in the libgfortran library. It has been fixed since gcc 4.7.3 (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54736 ).

Upvotes: 1

Related Questions