You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCC6.3.0版gfortran编译Fortran代码遇ALLOCATABLE组件IO错误求解决

Solution for gfortran 6.3.0 I/O Error with Allocatable Components in Derived Types

Got it, let's tackle this issue head-on. The error you're seeing happens because gfortran 6.3.0 doesn't support direct I/O (read/write) of derived types with allocatable components unless you explicitly define custom input/output procedures. Newer Intel Fortran versions handle this automatically (thanks to better support for Fortran 2003+ standards), but we need to adjust the code to play nice with the older GCC toolchain.

Here are two reliable, compiler-compatible fixes:

Option 1: Implement User-Defined I/O Procedures (Standard Fortran Approach)

This is the cleanest, most scalable solution—it aligns with Fortran standards and works across all compliant compilers. You'll add custom read/write routines directly to your TCosmoTheoryParams type definition.

Step 1: Update the Derived Type Definition

Add bindings for custom read/write procedures to your type:

type :: TCosmoTheoryParams
  ! Your existing components (example):
  real, allocatable :: HubbleParam(:)
  integer :: NumCosmoModels
  logical :: UseDarkEnergy
contains
  ! Bind custom procedures for formatted I/O
  procedure :: write_tcp => write_TCosmoTheoryParams
  procedure :: read_tcp => read_TCosmoTheoryParams
  generic :: write(formatted) => write_tcp
  generic :: read(formatted) => read_tcp
  
  ! Add these if you're using unformatted (binary) I/O:
  ! generic :: write(unformatted) => write_tcp
  ! generic :: read(unformatted) => read_tcp
end type TCosmoTheoryParams

Step 2: Write the Custom Read/Write Routines

These routines handle each component explicitly, including allocatable arrays:

! Custom write procedure for TCosmoTheoryParams
subroutine write_TCosmoTheoryParams(this, unit, iotype, v_list, iostat, iomsg)
  class(TCosmoTheoryParams), intent(in) :: this
  integer, intent(in) :: unit
  character(*), intent(in) :: iotype
  integer, intent(in) :: v_list(:)
  integer, intent(out) :: iostat
  character(*), intent(inout) :: iomsg

  ! Write non-allocatable components first
  write(unit, *, iostat=iostat, iomsg=iomsg) this%NumCosmoModels, this%UseDarkEnergy
  if (iostat /= 0) return

  ! Handle allocatable array: write size first, then data
  if (allocated(this%HubbleParam)) then
    write(unit, *, iostat=iostat, iomsg=iomsg) size(this%HubbleParam), this%HubbleParam
  else
    ! Use a sentinel value (-1) to mark unallocated arrays
    write(unit, *, iostat=iostat, iomsg=iomsg) -1
  end if
end subroutine write_TCosmoTheoryParams

! Custom read procedure for TCosmoTheoryParams
subroutine read_TCosmoTheoryParams(this, unit, iotype, v_list, iostat, iomsg)
  class(TCosmoTheoryParams), intent(inout) :: this
  integer, intent(in) :: unit
  character(*), intent(in) :: iotype
  integer, intent(in) :: v_list(:)
  integer, intent(out) :: iostat
  character(*), intent(inout) :: iomsg
  integer :: arr_size

  ! Read non-allocatable components
  read(unit, *, iostat=iostat, iomsg=iomsg) this%NumCosmoModels, this%UseDarkEnergy
  if (iostat /= 0) return

  ! Read array size, then allocate and read data
  read(unit, *, iostat=iostat, iomsg=iomsg) arr_size
  if (iostat /= 0) return

  if (arr_size > 0) then
    ! Deallocate existing array if needed
    if (allocated(this%HubbleParam)) deallocate(this%HubbleParam, stat=iostat)
    if (iostat /= 0) then
      iomsg = "Failed to deallocate HubbleParam in TCosmoTheoryParams"
      return
    end if
    ! Allocate new array
    allocate(this%HubbleParam(arr_size), stat=iostat)
    if (iostat /= 0) then
      iomsg = "Failed to allocate HubbleParam in TCosmoTheoryParams"
      return
    end if
    ! Read array data
    read(unit, *, iostat=iostat, iomsg=iomsg) this%HubbleParam
  else
    ! Mark array as unallocated
    if (allocated(this%HubbleParam)) deallocate(this%HubbleParam, stat=iostat)
  end if
end subroutine read_TCosmoTheoryParams

Step 3: Keep Your Original Read/Write Calls

Your existing lines:

read(F%Unit) FileSettings%TCosmoTheoryParams
Write(F%Unit) CosmoSettings%TCosmoTheoryParams

will now work as-is—gfortran will automatically call your custom procedures instead of trying to handle the type directly.


Option 2: Manual Component-by-Component I/O (Quick Fix)

If you don't want to modify the type definition, you can manually read/write each component of the derived type. This is simpler for small types but less maintainable if the type structure changes.

Replace Your Write Call

Instead of writing the entire type, write each component explicitly:

! Replace Write(F%Unit) CosmoSettings%TCosmoTheoryParams
with (CosmoSettings%TCosmoTheoryParams)
  write(F%Unit) NumCosmoModels, UseDarkEnergy
  if (allocated(HubbleParam)) then
    write(F%Unit) size(HubbleParam), HubbleParam
  else
    write(F%Unit) -1
  end if
end with

Replace Your Read Call

Similarly, read each component one by one:

! Replace read(F%Unit) FileSettings%TCosmoTheoryParams
integer :: arr_size
with (FileSettings%TCosmoTheoryParams)
  read(F%Unit) NumCosmoModels, UseDarkEnergy
  read(F%Unit) arr_size
  if (arr_size > 0) then
    if (allocated(HubbleParam)) deallocate(HubbleParam)
    allocate(HubbleParam(arr_size))
    read(F%Unit) HubbleParam
  else
    if (allocated(HubbleParam)) deallocate(HubbleParam)
  end if
end with

Why This Works

Newer Intel Fortran versions implement automatic derived type I/O for types with allocatable components (per Fortran 2003+ specs), but gfortran didn't fully support this until versions 8 and later. By explicitly handling the allocatable components in your code, you bypass gfortran 6.3.0's limitation.

内容的提问来源于stack exchange,提问作者johnhenry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:02:21