GFORTRAN_CONVERT_UNIT环境变量在某些平台上不起作用?

时间:2012-09-28 01:37:12

标签: linux fortran endianness gfortran

我有一个相当monolothic的代码,从未格式化的大端二进制文件中读取大量数据。通常,代码在bash脚本中运行,该脚本设置环境变量GFORTRAN_CONVERT_UNIT ='native; big_endian:60-70,80-89',然后使用其中一个单元号打开那些大端数据文件。这适用于Fedora和RHEL。但是,当我在Debian(以及包括Ubuntu和Linux Mint的衍生产品),OpenSUSE和Arch Linux上运行程序时,我在Fortran代码执行之前就收到了以下malloc错误:

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

为了进一步证明这个问题,我编写了两个Fortran程序,一个用来编写一个简单的大端数据文件,另一个用于读取它:

写程序:

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

阅读计划:

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

运行程序(这是使用GCC 4.7.1在32位OpenSUSE 12.2上,但在Ubuntu 32位时也失败):

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> 

显然,第一次尝试失败是因为它试图读取带有少量字节序读取的大端文件,但第二次尝试应该有效。实际上,它确实适用于许多系统。设置GFORTRAN_CONVERT_UNIT ='big_endian'而不是尝试挑选单位数也适用于所有系统。

我不认为这是一个32位与64位的问题,因为单片代码在64位服务器上,环境变量应该可以工作...我现在在32位上运行这些因为这就是我在笔记本电脑上的内容。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

此问题是由libgfortran库中的错误引起的。它自gcc 4.7.3开始修复(见https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54736)。