Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner

writing and reading derived types with pointers

Hi All,

I'm trying to save a write a derived type that contains a pointer to an unformatted file for later reading.  Below is a test version.  The derived type sol in module dType is separate because I'm patching together various Fortran codes (F95 and F77, etc).  The current version of the code "saves" sol1, but it seems to only save the pointer references, not their values, so when sol1 is deallocated, sol2 also becomes unreferenced.  I'm sure my hack on the UDTIO is not correct.

Any help would be appreciated (I'm still trying to figure out UDTIO).  Thanks

-joe

   module dType
      implicit none
      type, public :: sol
         integer:: n
         real(8), pointer:: vec(:)
      end type sol
   end module dType   
   
   module dType_io
      use dType
      implicit none
   contains

   subroutine write_sol(dtv, unit, iostat, iomsg)
      class(sol), intent(in) :: dtv
      integer, intent(in)             :: unit
      integer, intent(out)            :: iostat
      character(*), intent(inout)     :: iomsg

      write(unit, iostat=iostat, iomsg=iomsg) dtv%n
      write(unit, iostat=iostat, iomsg=iomsg) size(dtv%vec)
      write(unit, iostat=iostat, iomsg=iomsg) dtv%vec  
   end subroutine write_sol

   subroutine read_sol(dtv, unit, iostat, iomsg)
      class(sol), intent(inout)  :: dtv
      integer, intent(in)                 :: unit
      integer, intent(out)                :: iostat
      character(*), intent(inout)         :: iomsg

      integer allocSize

      ! read is sol type, but allocate pointer space as needed.
      read(unit, iostat=iostat, iomsg=iomsg) dtv%n
      read(unit, iostat=iostat, iomsg=iomsg) allocSize
      allocate( dtv%vec(allocSize) )      
      read(unit, iostat=iostat, iomsg=iomsg) dtv%vec  
   end subroutine read_sol
   end module dType_io
   
   program directAccess
      use dType
      implicit none
      integer, parameter :: dp = kind(0d0)
      type(sol):: sol1, sol2      
      integer solUnit, n, sze
      integer i
      
      sol1%n = 10
      allocate( sol1%vec(sol1%n) )
      sol1%vec = [ (real(i),i=1,sol1%n) ]  
      
      open(newunit=solUnit, file='test.sol', form='unformatted', status='replace', action='write')
      write(solUnit) sol1
      close(solUnit)
      
      open(newunit=solUnit, file='test.sol', form='unformatted', status='old', action='read')
      read(solUnit) sol2
      
      deallocate( sol1%vec ); nullify(sol1%vec) ! this will cause sol2 to lose reference
      
      close(solUnit)      
      stop
   end program directAccess
   
      
      
      

 

0 Kudos
14 Replies
Highlighted
Black Belt

The code doesn't have the

The code doesn't have the necessary declarations of the generic bindings or interfaces that specify that read_sol and write_sol are the procedures implementing defined IO for your type - the code is missing something like

INTERFACE READ(UNFORMATTED)
  MODULE PROCEDURE read_sol
END INTERFACE READ(UNFORMATTED)

and similarly for the WRITE(UNFORMATTED) interface.

The code should not compile without these.

You want to be using the very latest compiler (and perhaps even a bit later than that) if you are using UDDTIO.

(Edit to later add... I tried the current beta on the code, and I see it also fails to diagnose the body-text requirement for defined input/output of an object of derived type with pointer components.

Unrelated to UDDTIO, but I can't help myself - note that DEALLOCATION of a pointer also dissociates it - the nullify after the deallocate is just wearing your keyboard out prematurely.)

0 Kudos
Highlighted

You should also modify your

You should also modify your read and write routines to handle the case where the pointer is NULL.

e.g. On write, when pointer is null, write 0 for size and do not take size of the array.
On read, when allocSize is 0, nullify the pointer instead of allocating the pointer.

Jim Dempsey

0 Kudos
Highlighted
Beginner

Thanks Ian and Jim. As always

Thanks Ian and Jim. As always, very helpful!!! I also found Ian's previous post here https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/621651#comme... be very useful.

BTW, I am using the latest Intel compiler and the interface statements solved the problem.

cheers,

-joe

0 Kudos
Highlighted
Beginner

I guess I spoke too soon.  It

I guess I spoke too soon.  It appears when the size of the pointer becomes large (> than around 16390 elements), the write works OK, but when the read is executed it produces the IO errors:

On Write: iostat =    0 iomsg = OK
On Read: iostat =   67 iomsg = input statement requires too much data, unit -130, file C:\Users\jvallino\Projec

The read error occurs when it attempts to: read(unit, iostat=iostat, iomsg=iomsg) dtv%vec(1:allocSize)  As far as I can tell, IO limits are not being violated.  I'm guessing it is something simple, but I'm currently baffled.  Code is below.

   module dType
      implicit none
      type, public :: sol
         integer:: n
         real(8), dimension(:), pointer:: vec
      end type sol
   end module dType   
   
   module dType_io
      use dType
      implicit none
      interface read(unformatted)
         procedure read_sol
      end interface read(unformatted)
      interface write(unformatted)
         procedure write_sol
      end interface write(unformatted)
      
   contains
   subroutine write_sol(dtv, unit, iostat, iomsg)
      class(sol), intent(in) :: dtv
      integer, intent(in)             :: unit
      integer, intent(out)            :: iostat
      character(*), intent(inout)     :: iomsg

      write(unit, iostat=iostat, iomsg=iomsg) dtv%n
      write(unit, iostat=iostat, iomsg=iomsg) size(dtv%vec)
      write(unit, iostat=iostat, iomsg=iomsg) dtv%vec(1:size(dtv%vec))  
   end subroutine write_sol

   subroutine read_sol(dtv, unit, iostat, iomsg)
      class(sol), intent(inout)  :: dtv
      integer, intent(in)                 :: unit
      integer, intent(out)                :: iostat
      character(*), intent(inout)         :: iomsg

      integer allocSize

      ! read is sol type, but allocate pointer space as needed.
      read(unit, iostat=iostat, iomsg=iomsg) dtv%n
      read(unit, iostat=iostat, iomsg=iomsg) allocSize
      allocate( dtv%vec(allocSize) )      
      read(unit, iostat=iostat, iomsg=iomsg) dtv%vec(1:allocSize)  
   end subroutine read_sol
   end module dType_io
   
   program testUDDTIO
      use dType
      use dType_io
      implicit none
      integer, parameter :: dp = kind(0d0)
      type(sol):: sol1, sol2      
      integer solUnit, n, sze
      character*80 iomsg
      integer i, iostat
      
      sol1%n = 16390
      allocate( sol1%vec(sol1%n) )
      sol1%vec = [ (real(i),i=1,sol1%n) ]  
      iomsg = 'OK'
      open(newunit=solUnit, file='test.sol', form='unformatted', status='replace', action='write')
      write(solUnit, iostat=iostat,  iomsg=iomsg) sol1
      write(*,'(a,i4,2a)') 'On Write: iostat = ', iostat,' iomsg = ',trim(iomsg)
      close(solUnit)
      
      iomsg = 'OK'
      open(newunit=solUnit, file='test.sol', form='unformatted', status='old', action='read')
      read(solUnit, iostat=iostat,  iomsg=iomsg) sol2
      write(*,'(a,i4,2a)') 'On Read: iostat = ', iostat,' iomsg = ',trim(iomsg)

      deallocate( sol1%vec )
      
      close(solUnit)      
      stop
   end program testUDDTIO

The file produced during the write appears to be the correct size.  Also, when sol1%n is large enough to cause the read error, only the first 1022 elements are read into dtv%vec.

Thanks Again!

0 Kudos
Highlighted

Hopefully your last code

Hopefully your last code posting will reproduce the error for an Intel software support person. They should be able to investigate the issue with a reproducer. Please provide all the particulars: Compiler version, options used, 32/64-bit build, O/S.

Jim Dempsey

0 Kudos
Highlighted
Valued Contributor II

You need to allocate sol2

You need to allocate sol2 before the read or have the compiler flag /standard-semantics for it to auto-allocate on read.

0 Kudos
Highlighted

Andrew,

Andrew,

I believe the auto-allocate only applies to assignment (=) not reads. The option enabling this is realloc_lhs. For READ, the buffer argument is not an LHS entity.

Jim Dempsey

0 Kudos
Highlighted
Beginner

Even if you allocate sol2%vec

Even if you allocate sol2%vec prior to reading (which would defeat the usefulness of UDDTIO it would seem) the problem still occurs when the size exceeds ~16390 elements.  I did not try changing compiler options.

Using ifort 16.0.3.207 (build 20160415), x64 compiler

ifort /debug:full /Od /warn:interfaces /traceback /check:bounds /check:stack /libs:static /threads /dbglibs /Qmkl:parallel derivedTypeWriteRead.f90

Build and run on Windows 10.  

On a Linux box running version 16.0.2 20160204 of ifort, compiled with just "ifort derivedTypeWriteRead.f90" the exact same problem occurs.

For now, I've dropped trying to use UDDTIO and just went the non object route.

Thanks for everyone's help!

 

0 Kudos
Highlighted
Valued Contributor II

Your example works with 

Your example works with /standard-semantics for 18000 which is what I tested.on an x32 build.

 

 

 

0 Kudos
Highlighted
Valued Contributor II

Actually I take that back, it

Actually I take that back, it only reads the first 1022 elements....

0 Kudos
Highlighted
Beginner

OK, cause I just tried

OK, cause I just tried standard-semantics on both win and linux boxes and it did not work, but thanks for trying

0 Kudos
Highlighted
Black Belt

It is a compiler runtime bug.

It is a compiler runtime bug.  You can make it go away for the specific example if you increase things like the block size used for input/output (e.g. set FORT_BLOCKSIZE=256000 before running the program).

(Reallocation on assignment only applies when assigning to allocatables.  There are no allocatables in the program.)
 

0 Kudos
Highlighted
Employee

Thank Joe, Ian. I escalated

Thank Joe, Ian. I escalated the issues to Development.

(Internal tracking id: DPD200412514 - not diagnosing body-text requirement for defined input/output of an object of derived type with pointer components)

(Internal tracking id: DPD200412516 - Run-time iostat=67 reading > ~16390 elements w/UDDTIO)

0 Kudos
Highlighted
Employee

DPD200412514, the missed

DPD200412514, the missed diagnosis, will be fixed in a future major release (not the one later this year).

0 Kudos