在 Fortran 中多次循环后访问派生数据类型
Posted
技术标签:
【中文标题】在 Fortran 中多次循环后访问派生数据类型【英文标题】:Accessing derived data types after several loops in Fortran 【发布时间】:2018-07-08 14:21:15 【问题描述】:我有以下代码:
program testdatatype
integer(8), parameter :: Stot= 2
integer(8), dimension(Stot) :: Nf
integer(8) :: f, s, Qind
integer(8), dimension(:, :), allocatable :: NqG
real(16), dimension(:, :, :), allocatable :: d3xnormfac
type NqGtype
integer(8), dimension(:, :), allocatable :: NqGvalT
end type NqGtype
type(NqGtype), dimension(Stot) :: NqGT
type d3xnormfactype
real(16), dimension(:, :, :), allocatable :: d3xnormfacvalT
end type d3xnormfactype
type(d3xnormfactype), dimension(Stot) :: d3xnormfacT
! ----------------------------------------------------
! LOOP 1.1:
do s= 1, Stot, 1
Nf(s)= 2d0
write(*, *) 'NfLoop1.1= ', Nf(s)
end do
! LOOP 1.2:
do s= 1, Stot, 1
write(*, *) 'NfLoop1.2= ', Nf(s)
end do
! ----------------------------------------------------
! LOOP 2.1:
do s= 1, Stot, 1
allocate(NqG(Nf(s), Stot))
do f= 1, Nf(s), 1
NqG(f, s)= 5d0
NqGT(s)%NqGvalT= NqG
write(*, *) 'NqGLoop2.1= ', NqG(f, s)
write(*, *) 'NqGTLoop2.1= ', NqGT(s)%NqGvalT(f, s)
end do
deallocate(NqG)
end do
! LOOP 2.2:
do s= 1, Stot, 1
do f= 1, Nf(s), 1
write(*, *) 'NqGTLoop2.2= ', NqGT(s)%NqGvalT(f, s)
end do
end do
! ----------------------------------------------------
! LOOP 3.1:
do s= 1, Stot, 1
do f= 1, Nf(s), 1
allocate(d3xnormfac(Nf(s), Stot, NqGT(s)%NqGvalT(f, s)))
do Qind= 1, NqGT(s)%NqGvalT(f, s)
d3xnormfac(f, s, Qind)= 153d12
d3xnormfacT(s)%d3xnormfacvalT= d3xnormfac
write(*, *) 'd3xnormfacLoop3.1= ', d3xnormfac(f, s, Qind)
write(*, *) 'd3xnormfacTLoop3.1= ', d3xnormfacT(s)%d3xnormfacvalT(f, s, Qind)
end do
deallocate(d3xnormfac)
end do
end do
! LOOP 3.2:
do s= 1, Stot, 1
do f= 1, Nf(s), 1
do Qind= 1, NqGT(s)%NqGvalT(f, s)
write(*, *) 'd3xnormfacTLoop3.2= ', d3xnormfacT(s)%d3xnormfacvalT(f, s, Qind)
end do
end do
end do
! ----------------------------------------------------
end program testdatatype
我在 mpif90 编译器上编译这个 .f90 文件。正如您在运行此代码时所看到的,很明显循环 1.1 中的 write
语句给出的结果与循环 1.2 中的相同,也就是说,Nf(:)
的值对于循环 1.1 之外的所有 s 值都是正确的。 Loop 2.1 和 Loop 2.2 也是如此(这次创建了派生数据类型)。循环 1 的输出如下:
NfLoop1.1= 2
NfLoop1.1= 2
NfLoop1.2= 2
NfLoop1.2= 2
对于创建它的循环(循环 2.1)之外的任何 f 和 s 值(在循环 2.2 中),我可以调用数据类型 NqGT(s)%NqGT(f, s)
的任何正确值。到目前为止没有问题。当我使用 Loop 2 运行 Loop 1 变量时,会给出以下输出:
NfLoop1.1= 2
NfLoop1.1= 2
NfLoop1.2= 2
NfLoop1.2= 2
NqGLoop2.1= 5
NqGTLoop2.1= 5
NqGLoop2.1= 5
NqGTLoop2.1= 5
NqGLoop2.1= 5
NqGTLoop2.1= 5
NqGLoop2.1= 5
NqGTLoop2.1= 5
NqGTLoop2.2= 5
NqGTLoop2.2= 5
NqGTLoop2.2= 5
NqGTLoop2.2= 5
此外,当将循环 1 变量运行到循环 2 派生数据类型中时,这些数据类型又与循环 3 一起使用,给出以下输出:
NfLoop1.1= 2
NfLoop1.1= 2
NfLoop1.2= 2
NfLoop1.2= 2
NqGLoop2.1= 5
NqGTLoop2.1= 5
NqGLoop2.1= 5
NqGTLoop2.1= 5
NqGLoop2.1= 5
NqGTLoop2.1= 5
NqGLoop2.1= 5
NqGTLoop2.1= 5
NqGTLoop2.2= 5
NqGTLoop2.2= 5
NqGTLoop2.2= 5
NqGTLoop2.2= 5
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.1= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= -1.83360386755485123703987599430319601E-2466
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 0.00000000000000000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
d3xnormfacTLoop3.2= 153000000000000.000000000000000000000
但是,当我尝试对循环 3.1 执行相同操作时,我无法再获得派生数据类型 d3xnormfacT(s)%d3xnormfacvalT(f, s, Qind)
的所有正确值,也就是说,循环 3.2 中打印的数据类型不等于这些值在循环 3.1 中打印相同的数据类型(某些值是正确的,但其他值不是)。我怎样才能解决这个问题?我一定遗漏了一些东西(指针和/或派生数据类型的分配?)
【问题讨论】:
请贴出你运行代码得到的输出,以及你使用的编译命令。 对我来说,NqGT(1)%NqGvalT
没有分配,所以即使是循环 2.1 也会出现代码错误
代码需要 Fortran 2003 编译器。它似乎对我有用。您使用的是哪个编译器以及哪些编译器选项?
欢迎您,请务必使用tour 并阅读How to Ask。尝试始终提供基本信息,例如您正在使用的编译器、其版本、使用的编译器标志以及包含所有错误消息的输出。
我已经编辑了文本以包含输出。在命令行我有 之后我将可执行文件称为 任何想法为什么这些数字在从三个循环的派生数据类型中分配后不能转换?跨度>
【参考方案1】:
在循环 3.1 中,您只设置了 d3xnormfac
的特定索引,然后将整个 d3xnormfac
数组分配给 d3xnormfacT(s)%d3xnormfacvalT
。因为d3xnormfac
被解除分配,然后多次分配,所以不能保证之前分配的值仍然被设置。
由于您的特定循环顺序,d3xnormfac(:,1,:)
中的值未初始化。根据编译器是否将d3xnormfac
重新分配到同一位置以及内存是否已清理,这些值最终可能是正确的。对于我的英特尔(使用-assume realloc-lhs
允许自动分配),大多数值都是正确的。如您所见,对于我的 gfortran,大多数值都不正确。行为可能也取决于真实的类型,这也解释了您的观察。
了解这一点的一个好方法是在分配后初始化每个值。修改代码以在循环 3.1 中添加:
allocate(d3xnormfac(Nf(s), Stot, NqGT(s)%NqGvalT(f, s)))
d3xnormfac = -1234 ! -- Added this line
do Qind= 1, NqGT(s)%NqGvalT(f, s)
产生以下结果:
mach5% ifort -assume realloc_lhs -check all -warn all -traceback -g main.f90 && ./a.out
NfIN= 2
NfIN= 2
NfOUT= 2
NfOUT= 2
NqGIN= 15
NqGTIN= 15
NqGIN= 15
NqGTIN= 15
NqGIN= 15
NqGTIN= 15
NqGIN= 15
NqGTIN= 15
NqGTOUT= 15
NqGTOUT= 15
NqGTOUT= 15
NqGTOUT= 15
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacIN= 153000000000000.000000000000000000
d3xnormfacTIN= 153000000000000.000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= -1234.00000000000000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
d3xnormfacTOUT= 153000000000000.000000000000000000
您可以看到仍然设置为 -1234 的部分。
澄清后
我现在看到这个问题来自对可分配数组如何属于派生类型的误解。
d3xnormfacT(s)%d3xnormfacvalT
是它自己的可分配数组。它是等级 3 并且(直到分配)是未分配的。它(通常)使用常规分配语句分配,例如:
allocate(d3xnormfacT(s)%d3xnormfacvalT((Nf(s), Stot, NqGT(s)%NqGvalT(f, s)))
你没有这样做。您正在通过(无意中)使用 fortran 的高级功能绕过传统分配:自动左侧 (lhs) 分配。当一个数组被分配一个与其形状匹配的值时,该数组被分配或重新分配以匹配。更多信息在这里:Automatic array allocation upon assignment in Fortran
您的陈述:
d3xnormfacT(s)%d3xnormfacvalT= d3xnormfac
实际上是同时做两件事。首先,d3xnormfacT(s)%d3xnormfacvalT
被分配以匹配d3xnormfac
的大小,因为d3xnormfacT(s)%d3xnormfacvalT
匹配d3xnormfac
的形状(3 维)。其次,新分配的d3xnormfacT(s)%d3xnormfacvalT
被分配与d3xnormfac
相同的值。 (没有人指向其他任何东西。)
您应该更改代码以不使用此自动 lhs 分配。 2003 标准允许这种自动 lhs 分配,但某些编译器(英特尔直到 2017 年)故意默认不支持它。我个人认为这是危险且不直观的,所以我通常会避免它。对于不了解它的开发人员来说,此功能可能是一个“陷阱”。防止这种情况发生的 gfortran(我猜你正在使用,你只指定 mpif90
这只是一个包装器)标志是 -fno-realloc-lhs
。
更改代码后,您将更好地理解我的其余答案,这就是您看到问题的真正原因。
编辑:正如@eriktous 指出的那样,循环 2 中存在同样的问题,但循环顺序意味着没有未初始化的值被放入输出中。我真的不明白为什么s
索引both 派生数据类型和数组的最外层维度。也许是因为这只是一个玩具箱。如果您要扩展此代码,请务必解决这两个问题。
【讨论】:
顺便说一句,循环 2.1 中也存在同样的问题。 好点。但是,它不会显示为输出中的任何初始化值,因为NqGvalT
只是一个二维数组。
@eriktous 编辑了这个效果
分配 NqGT(s)%NqGvalT 和 d3xnormfacT(s)%d3xnormfacvalT 的 lhs 分配到底是什么意思?我正在使用以下语句在循环中分配数组: allocate(d3xnormfac(Nf(s), Stot, NqGT(s)%NqGvalT(f, s))) 我应该如何编写这部分或数据类型的声明提前?
对...这正是我问原始问题的原因,但您当时没有回答。 d3xnormfacT(s)% d3xnormfacvalT
和 d3xnormfac
是完全不同的东西。它们在内存中占据不同的空间,不会一起分配。我将更新答案,以便为初学者提供更好的概述。【参考方案2】:
在分配后添加行d3xnormfac= 1234
@Ross 暗示似乎可以确保初始化。当 Loop 2 更改为以下内容时:
! LOOP 2.1:
do s= 1, Stot, 1
allocate(NqGT(1)%NqGvalT(Nf(s), Stot))
allocate(NqG(Nf(s), Stot))
do f= 1, Nf(s), 1
NqG(f, s)= 5d0
write(*, *) 'NqGLoop2.1= ', NqG(f, s)
NqGT(1)%NqGvalT= NqG(:, :)
write(*, *) 'NqGTLoop2.1= ', NqGT(1)%NqGvalT(f, s)
end do
deallocate(NqG)
deallocate(NqGT(1)%NqGvalT)
end do
! LOOP 2.2:
write(*, *) 'NqGTLoop2.2= ', NqGT(1)%NqGvalT(:, :)
直接分配派生数据类型数组时,解除分配数组时会出现以下错误:
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x103880e46
#1 0x10388060c
#2 0x7fff59ff8f59
#3 0x1039095d5
#4 0x10390975e
#5 0x10390d0dd
#6 0x10367fbef
#7 0x10367fc9e
Segmentation fault: 11
因此,lhs 自动分配派生数据类型是最初没有给出此错误的原因。当只分配d3xnormfac
并让d3xnormfacT(s)%d3xnormfacvalT
自动分配时,可以在3 次循环之后访问正确的数组值而不会出错,因为派生数据类型数组不会在内部循环中释放。只要派生的数据类型数组具有恒定的维度,我怀疑以后应该不是问题。至于数组值的完整初始化,@Ross 的解决方案似乎有效。如果谨慎使用,这种情况下 lhs 自动分配可以工作。
【讨论】:
以上是关于在 Fortran 中多次循环后访问派生数据类型的主要内容,如果未能解决你的问题,请参考以下文章