Reputation: 21
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
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