让我考虑一个返回一个的函数allocatable数组的函数。是否应该在赋值之前分配保存结果的数组变量(在函数外部)?
例如,考虑以下程序
\nprogram mem\n implicit none\n\n interface\n function get_matrix() result(res)\n real(kind=kind(0.d0)), allocatable :: res(:,:)\n end function get_matrix\n end interface\n \n real(kind=kind(0.d0)), allocatable :: w(:,:)\n\n allocate(w(2,2)) ! Is this necessary?\n w=get_matrix()\n deallocate(w)\n\nend program mem\n\nfunction get_matrix() result(res)\n real(kind=kind(0.d0)), allocatable :: res(:,:)\n\n allocate(res(2,2))\n res = 0.d0\n res(1, 1) = 1.d0\n res(2, 2) = 1.d0\nend function get_matrix\nRun Code Online (Sandbox Code Playgroud)\n根据this和thisres ,为 的 结果分配的数组get_matrix一旦超出范围就会被释放。
w对主程序中未分配变量的赋值是否会延长结果的范围get_matrix?换句话说,如果我allocate(w(2,2))在主程序中省略,我会得到未定义的行为吗?
省略allocate(w(2,2))并使用gfortran …
在下面的简单程序中,我陷入了派生类型的可分配数组成员的分段错误。此分段错误仅在我尝试过的一台计算机(在openSUSE上使用Intel Fortran 14.0.3)上,而在另一台计算机(在Ubuntu上使用Intel Fortran 14.0.2)上则没有。另外,如果我更改程序中的整数参数之一,程序将正常结束。
有人能重现这个问题吗?有人可以告诉我代码有什么问题吗?
以下是三个源代码文件。
main_dbg.f90
..是否发生分段错误取决于n1and n2在此文件中的值。
PROGRAM dbg
USE tktype
USE mymodule, ONLY : MyClass, MyClass_constructor
IMPLICIT NONE
INTEGER(I4B) :: n1,n2,n3
TYPE(MyClass) :: o_MyClass
n1=23
n2=32
! .. this does not work.
! n2=31
! .. this works.
n3 = n1*n2
write(*,'(1X,A,I10)') 'n1=', n1
write(*,'(1X,A,I10)') 'n2=', n2
write(*,'(1X,A,I10)') 'n3=', n3
o_MyClass = MyClass_constructor(n1, n2, n3)
call o_MyClass%destructor()
write(*,*) '***************************'
write(*,*) ' Normal End :) '
write(*,*) '***************************'
END PROGRAM dbg
Run Code Online (Sandbox Code Playgroud)
strange.f90
..分段错误发生forall …
fortran memory-management segmentation-fault allocatable-array
我正在使用GNU Fortran(GCC)4.8.2
我想从名称列表中读取可分配数组。但是我事先不知道必须向可分配数组中读取多少个元素,因此我无法在读取名称列表之前对其进行分配。
这是我的名单:namelist.nml:
&SECTION_1
intList = 5,6,7
&END
Run Code Online (Sandbox Code Playgroud)
这是我的程序:namelist.f08:
program namelist
implicit none
integer, allocatable :: intList(:)
integer :: U ! Unit to read the namelist file
namelist /SECTION_1/ intList
!allocate(intList(3)) ! <-- If I uncomment this, the program works.
open(NEWUNIT=U, file="namelist.nml", status='OLD', recl=80, delim='APOSTROPHE')
rewind(U)
read(U, nml=SECTION_1)
close(U)
write (*,*) intList
end program namelist
Run Code Online (Sandbox Code Playgroud)
如果我取消标记行的注释,程序将运行,但是,正如我之前说的,我无法在分配之前读取名称列表。有人知道如何做到这一点吗?
我想知道 fortran 可分配数组的内部存储器表示是什么。
我理解这比原始指针更复杂一点,因为形状和等级也必须存储。
我还猜测它依赖于实现,因为我在Fortran 2003 标准中找不到信息。
但是,我想知道使用哪种结构来表示可分配数组(即使只针对一个编译器)。
我知道这个问题有点宽泛,但我们将不胜感激。
一个简单的代码:
\n\nprogram main\ninteger, allocatable :: A(:,:)\ninteger :: B(3,4)\nB=1\nA = B !A will get allocated, with the same shape and bounds as B\nend program main\nRun Code Online (Sandbox Code Playgroud)\n\n编译上面的代码:gfortran-8 -std=f2008 -fcheck=all -Wall -Wextra -fbounds-check -fimplicit-none array.f90
我收到以下警告:
\n\nWarning: \xe2\x80\x98a.offset\xe2\x80\x99 may be used uninitialized in this function\nWarning: \xe2\x80\x98a.dim[0].lbound\xe2\x80\x99 may be used uninitialized in this function \nWarning: \xe2\x80\x98a.dim[0].ubound\xe2\x80\x99 may be used uninitialized in this function [-Wmaybe-uninitialized]
有人知道我为什么收到这些警告吗?
\nfortran gfortran compiler-warnings gcc-warning allocatable-array
我正在尝试编写一个程序,其中我希望可分配数组的A等级为 1、2 或 3,具体取决于我在运行时的输入。我想这样做,因为后续操作A是相似的,并且我在模块中定义了一个work带有模块过程的接口,当执行该模块过程时A,会给出所需的结果。
我目前正在做的是这样的:
program main
implicit none
integer :: rank,n=10
real*8, allocatable :: A1(:)
real*8, allocatable :: A2(:,:)
read (*,*) rank
if (rank.eq.1) then
allocate (A1(n))
else if (rank.eq.2) then
allocate (A2(n,n))
end if
! operate on the array
if (rank.eq.1) then
call work(A1)
else if (rank.eq.2) then
call work(A2)
end if
end program
Run Code Online (Sandbox Code Playgroud)
如果我可以选择 的等级A,事情会容易得多,因为这样就if不需要这些陈述了。也许这是不可能的,但感谢所有帮助。
一般来说,我想重命名派生类型中的可分配变量,这些变量通过子例程参数传递.使用'derived%type_xx'编写所有内容并不是那么令人愉快.此外,我不想花费额外的内存来将派生类型的值复制到一个新的变量,这需要新的分配内存.此外,我知道可分配数组比指针更受欢迎,原因有很多.我尝试定义指向可分配变量的指针,但失败了.我试过这个,因为我想简化我的代码,既可读也不太长.我想知道是否有办法实现目标?谢谢.
这是演示代码:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1) :: input
input%longname_1 = input%longname_1 + input%longname_2 ! Use one line to show what I mean
END SUBROUTINE
Run Code Online (Sandbox Code Playgroud)
这是失败的:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1),TARGET :: input
REAL,POINTER :: a => input%longname_1 &
& b => input%longname_2
a …Run Code Online (Sandbox Code Playgroud) 由于Fortran 2003可以使用可变长度的字符串.我不想以古老的方式工作并声明一个恒定的字符串长度,而是想动态地读取我的名单中的字符串.
考虑一下该计划
program bug
implicit none
character(:), allocatable :: string
integer :: file_unit
namelist / list / string
open(newunit=file_unit,file='namelist.txt')
read(unit=file_unit,nml=list)
write(*,*) string
close(file_unit)
end program bug_namelist
Run Code Online (Sandbox Code Playgroud)
以及namelist.txt文件中包含的小名单:
&list
string = "abcdefghijkl"
/
Run Code Online (Sandbox Code Playgroud)
如果我用GCC 8.2.0编译带有激进的调试标志,我得到
Warning: ‘.string’ may be used uninitialized in this function [-Wmaybe-uninitialized]
Run Code Online (Sandbox Code Playgroud)
在runtine,什么都没有打印出来,这就出现了:
Fortran runtime warning: Namelist object 'string' truncated on read.
Run Code Online (Sandbox Code Playgroud)
使用具有类似调试标志的英特尔编译器17.0.6,没有编译时标志和以下运行时错误:
forrtl: severe (408): fort: (7): Attempt to use pointer STRING when it is not associated with a target
Run Code Online (Sandbox Code Playgroud)
这表明namelist功能无法"自行"分配可变长度字符串,因为如果我添加该行
allocate(character(len=15) :: string)
Run Code Online (Sandbox Code Playgroud)
错误消失了.这是预期的行为吗?或者它是编译器的缺陷?
我有以下模块,其中包含一个可分配变量,该变量在模块中定义,在子例程中分配,然后也在第一个子例程调用的第二个子例程中使用。在这种情况下,我是否必须将变量传递给第二个子例程并声明INTENT(inout)?或者因为它是一个全局变量,所以不需要作为参数传递?
MODULE test
IMPLICIT NONE
SAVE
REAL,ALLOCATABLE,DIMENSION(:,:,:) :: total
CONTAINS
!--- 1st subroutine
SUBROUTINE my_subr1(n,m,z)
IMPLICIT NONE
INTEGER,INTENT(in) :: n,m,z
ALLOCATE(total (n,m,z))
total=.9
CALL my_subr2(n)
END SUBROUTINE my_subr1
!-- 2nd subroutine
SUBROUTINE my_subr2(n)
IMPLICIT NONE
INTEGER,INTENT(in) :: n
total(n,:,:)=total(n-1,:,:)
END SUBROUTINE my_subr2
END MODULE test
Run Code Online (Sandbox Code Playgroud) I read on many posts on Stack Overflow that an allocatable array is deallocated when it is passed in a subroutine where the dummy argument is intent(out).
If I consider the following code :
program main
real, dimension(:), allocatable :: myArray
integer :: L=8
allocate(myArray(1:L))
call initArray(myArray)
print *, myArray
contains
subroutine initArray(myArray)
real, dimension(:), intent(out) :: myArray
myArray(:) = 10.0
end subroutine initArray
end program main
Run Code Online (Sandbox Code Playgroud)
输出是正确的。因此,当发生释放时,内存被释放,但数组形状保持不变。准确吗?任何详细的解释将不胜感激。
我阅读了有关该主题的不同帖子(我可以在 Fortran 中使用可分配数组作为意图(输出)矩阵吗?,将可分配变量传递到具有不可分配参数的子例程的效果是什么?,...)。所以我知道数组已被释放,但我想了解这是什么意思,因为在我的代码中,大小被保留,而且我也对这段代码的工作原理感到惊讶。
当从使用g95编译器转换到gfortran时,当我尝试编译之前已经工作的代码时出现以下错误
Error: Allocatable array ' ' at (1) must have a deferred shape
Run Code Online (Sandbox Code Playgroud)
这发生在我所有可分配数组的所有子程序中.一个例子如下.
SUBROUTINE TEST(name,ndimn,ntype,nelem,npoin,nface,inpoel,coord,face)
IMPLICIT NONE
integer:: i, j,testing
integer, INTENT(OUT)::ndimn,ntype,nelem,npoin,nface
integer, allocatable, dimension(1:,1:), INTENT(OUT)::inpoel
real::time, dummy
real, allocatable, dimension(1:,1:), INTENT(OUT)::coord
integer, allocatable, dimension(1:,1:), INTENT(OUT)::face
character(len=13)::name
character(len=11)::name3
name='testgrid.dat'
name3='testgeo.dat'
open (unit=14, file='testgrid2.dat', status='old')
read(14,*)
read(14,*)
read(14,*)
read(14,*) ndimn, ntype
read(14,*)
read(14,*) nelem, npoin, nface
read(14,*)
allocate(inpoel(ntype,nelem+1),coord(ndimn,npoin+1),face(ntype,nface+1))
Run Code Online (Sandbox Code Playgroud)
如何使用gfortran编译此代码?
我想知道在现代 Fortran 中是否可以使用其本身或其中的一部分来分配可分配数组来执行此操作。这是一个简单的例子:
module modu
implicit none
type :: t
integer :: i
end type
contains
subroutine assign(a,b)
type(t), allocatable, intent(out) :: a(:)
type(t), intent(in) :: b
allocate(a(1))
a(1) = b
end subroutine
end module
!----------------------
program test
use modu
implicit none
type(t), allocatable :: a(:)
allocate(a(1))
a(1)%i = 2
call assign(a, a(1))
print*, a(1)%i
end program
Run Code Online (Sandbox Code Playgroud)
此代码使用 ifort 18 给出正确的答案,并使用 gfortran 7.4 返回“分段错误”。
注意:原来的问题有点复杂,因为call assign(a, a(1))应该call assign(a, a(1)+b)用运算符 + 正确重载来替换,但结论(尊重 ifort 和 gfortran)是相同的。