With the following test case and no optimization, the dtp pointer is duplicated resulting in the dtp-rec values getting mixed up during consecutive writes: program avl implicit none real dt, t, a(10) integer i, place dt = 1.e-6 a = real( (/ (i, i=1, 10) /) ) open(unit=11, file='a.dat', access='stream') open(unit=12, file='b.dat', access='stream') do i = 1, 10 t = i * dt write(11) t write(12) a end do close(11) close(12) end program avl Test case from Steve Kargl. The end result should be a.dat file of length 40 and b.dat file of length 400. The result is: -rw-rw-r-- 1 jerry jerry 396 Sep 12 19:32 a.dat -rw-rw-r-- 1 jerry jerry 436 Sep 12 19:32 b.dat With -O1 this program works fine. With gdb you can see the transfer calls given the same dtp pointer for both files.
It fails at all optimization levels on FreeBSD.
(In reply to comment #1) > It fails at all optimization levels on FreeBSD. If a.dat and b.dat are still there, nothing changes in file size. Make sure you removed them before running the program.
Assembly output which does not work because it is using the same block of memory for the st_parameter_dt structure for both WRITEs, the file position pointer is in this structure, but not set before the calls because it is suppose to be wherever it was left at. movl $.LC1, -368(%ebp) movl $13, -364(%ebp) movl $11, -372(%ebp) movl $0, -376(%ebp) leal -376(%ebp), %eax movl %eax, (%esp) call _gfortran_st_write snip movl $.LC1, -368(%ebp) movl $16, -364(%ebp) movl $12, -372(%ebp) movl $0, -376(%ebp) leal -376(%ebp), %eax movl %eax, (%esp) call _gfortran_st_write Assembly output with -O1 shows that in this case, two separate blocks of memory are being used for the two separate st_parameter_dt structures. In this case the two writes are kept independent as they should be. movl $.LC0, -324(%ebp) movl $13, -320(%ebp) movl $11, -328(%ebp) movl $0, -332(%ebp) movl %esi, -624(%ebp) movl %esi, (%esp) call _gfortran_st_write snip movl $.LC0, -600(%ebp) movl $16, -596(%ebp) movl $12, -604(%ebp) movl $0, -608(%ebp) leal -608(%ebp), %ebx movl %ebx, (%esp) call _gfortran_st_write The STREAM I/O assumes that the dtp structure is global, static, and unique to each unit. Evidently this is not the case. To fix this, we can allocate the POS pointer for STREAM within the gfc_unit structure which is allocated at run time when OPENed and will remain static and unique. I will proceed with a patch to do this.
Subject: Bug number PR29053 A patch for this bug has been added to the patch tracker. The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2006-09/msg00571.html
Subject: Bug 29053 Author: jvdelisle Date: Fri Sep 15 13:16:15 2006 New Revision: 116970 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116970 Log: 2006-09-14 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR libgfortran/29053 * io.h (gfc_unit): Add variable, strm_pos, to track STREAM I/O file position. * file_pos.c (st_rewind): Set strm_pos to beginning. * open.c (new_unit): Initialize strm_pos. * read.c (read_x): Bump strm_pos. * inquire.c (inquire_via_unit): Return strm_pos value. * transfer.c (read_block),(read_block_direct),(write_block) (write_buf): Seek to strm_pos - 1. Update strm_pos when done. (pre_position): Initialize strm_pos. (data_transfer_init): Set strm_pos if DT_HAS_REC. (finalize_transfer): Flush file, no need to update strm_pos. Modified: trunk/libgfortran/ChangeLog trunk/libgfortran/io/file_pos.c trunk/libgfortran/io/inquire.c trunk/libgfortran/io/io.h trunk/libgfortran/io/open.c trunk/libgfortran/io/read.c trunk/libgfortran/io/transfer.c
Subject: Bug 29053 Author: jvdelisle Date: Fri Sep 15 13:32:12 2006 New Revision: 116971 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=116971 Log: 2006-09-15 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR libgfortran/29053 * gfortran.dg/streamio_9.f90: New test. * gfortran.dg/streamio_10.f90: New test. Added: trunk/gcc/testsuite/gfortran.dg/streamio_10.f90 trunk/gcc/testsuite/gfortran.dg/streamio_9.f90 Modified: trunk/gcc/testsuite/ChangeLog
Fixed on 4.2, will not go to 4.1.
*** Bug 28747 has been marked as a duplicate of this bug. ***