gpt4 book ai didi

pointers - Ifort : move_alloc() on attribute of a Pointer, intent(in) 触发错误

转载 作者:行者123 更新时间:2023-12-04 18:40:36 29 4
gpt4 key购买 nike

我想扩展一个结构的可分配属性和 MOVE_ALLOC() 似乎是最干净的方法。所以我使用 Pointer, Intent(in) 创建了一个例程指向结构作为参数并尝试调用:

Type(STRUCT1), Pointer, Intent(in)  :: str1
...
call MOVE_ALLOC(TO= str1%arrayofint , FROM= temparray)

哪里 str1是指向结构的指针, arrayofint是要扩展的属性。见子程序 LOC_extendsecond()以下示例代码。 编译器 ifort 返回以下错误:
Source1.f90(91): error #7999: The FROM or TO arguments of a MOVE_ALLOC reference must not be INTENT(IN).   [MOVE_ALLOC]

好像 str1%arrayofint分别是 Intent(in) . 记住指针str1Intent(in) , 是尖头结构的属性 str1%arrayofint被视为 Intent(in) ?

为了调查这个问题,我尝试不使用 MOVE_AllOC()并发现解除分配或分配 str1%arrayofint在例程中不会触发来自 ifort 的任何错误或警告。见子程序 LOC_extendfirst()示例代码。

我的一位同事提出了一种解决方法(感谢 Luc!):创建指针的本地副本并 MOVE_AllOC()可以使用指针的这个本地副本调用,而不会引发错误。见子程序 LOC_extendthird()示例代码。
Type(STRUCT1), Pointer, Intent(in)  :: str1
Type(STRUCT1), Pointer :: str2
str2=>str1
...
call MOVE_ALLOC(TO= str2%arrayofint , FROM= temparray)

这是示例代码:
Module Source1

Implicit None

Public :: STRUCT1

Private

Type STRUCT1
Integer, dimension(:), allocatable :: arrayofint

End Type STRUCT1

Contains

Subroutine newstruct1(str1,ier,errmsg)

Type(STRUCT1), Pointer, Intent(inout) :: str1
Integer, Intent(out) :: ier
character(len=256), Intent(out) :: errmsg

ier=0
allocate(str1,stat=ier, errmsg=errmsg)
if( ier>0) return

allocate(str1%arrayofint(2),stat=ier, errmsg=errmsg)
if( ier>0) return

End Subroutine newstruct1

Subroutine LOC_extendfirst(str1,targetsize,ier,errmsg)
Type(STRUCT1), Pointer, Intent(in) :: str1
Integer, Intent(out) :: ier
character(len=256), Intent(out) :: errmsg
Integer, Intent(in) :: targetsize

Integer,dimension(1) :: shp
Integer :: newsize , formersize
Integer, dimension(:), allocatable :: temparray

ier=0

shp=shape(str1%arrayofint)
formersize=shp(1)
if (targetsize .GT. formersize) then
newsize=MAX(targetsize,2*formersize)
allocate(temparray(newsize),stat=ier, errmsg=errmsg)
if( ier>0) then; return ; endif
temparray(1:formersize)=str1%arrayofint
allocate(temparray(formersize),stat=ier, errmsg=errmsg)
if( ier>0) then; return ; endif
temparray=str1%arrayofint
if(allocated(str1%arrayofint)) deallocate(str1%arrayofint)
allocate(str1%arrayofint(newsize),stat=ier, errmsg=errmsg)
if( ier>0) then; return ; endif
str1%arrayofint(1:formersize)=temparray
if(allocated(temparray)) deallocate(temparray)
endif

End Subroutine LOC_extendfirst

Subroutine LOC_extendsecond(str1,targetsize,ier,errmsg)
Type(STRUCT1), Pointer, Intent(in) :: str1
Integer, Intent(out) :: ier
character(len=256), Intent(out) :: errmsg
Integer, Intent(in) :: targetsize

Integer,dimension(1) :: shp
Integer :: newsize , formersize
Integer, dimension(:), allocatable :: temparray

ier=0

shp=shape(str1%arrayofint)
formersize=shp(1)
if (targetsize .GT. formersize) then
newsize=MAX(targetsize,2*formersize)
allocate(temparray(newsize),stat=ier, errmsg=errmsg)
if( ier>0) then; return ; endif
temparray(1:formersize)=str1%arrayofint
! TODO uncomment the following line to get error from ifort
call MOVE_ALLOC(TO= str1%arrayofint , FROM= temparray)
endif

End Subroutine LOC_extendsecond

Subroutine LOC_extendthird(str1,targetsize,ier,errmsg)
Type(STRUCT1), Pointer, Intent(in) :: str1
Integer, Intent(out) :: ier
character(len=256), Intent(out) :: errmsg
Integer, Intent(in) :: targetsize

Integer,dimension(1) :: shp
Integer :: newsize , formersize
Integer, dimension(:), allocatable :: temparray

Type(STRUCT1), Pointer :: str2
ier=0

str2=>str1
shp=shape(str2%arrayofint)
formersize=shp(1)
if (targetsize .GT. formersize) then
newsize=MAX(targetsize,2*formersize)
allocate(temparray(newsize),stat=ier, errmsg=errmsg)
if( ier>0) then; return ; endif
temparray(1:formersize)=str1%arrayofint
call MOVE_ALLOC(TO= str2%arrayofint , FROM= temparray)

endif

End Subroutine LOC_extendthird

End Module Source1

在 Windows 上调用 ifort 19.0.2.190 IA32,使用 ifort /nologo /debug:full /Od /debug-parameters:all /warn:unused /warn:truncated_source /warn:uncalled /warn:interfaces /Qsave /traceback /check:pointer /check:bounds /check:uninit /libs:static /threads /dbglibs /c /Qm32 "Source1.f90"产生错误。

相反,在 Debian 上使用来自 gcc 6.3.0 的 gfortran 使用 gfortran -c Source1.f90 -Wall不会导致任何错误:它只显示有关未使用功能的警告。

我是 Fortran 的新手。我知道 Fortran 指针比 C 指针包含更多的数据,所以我想知道是否修改属性 str1%arrayofint正确为 str1Pointer, Intent(in) ,就像在函数中修改 str1->arrayofint 是正确的,因为指针 str1 是按值传递的。

如何解决 ifort 和 gfortran 之间的行为差​​异? ifort 是否正确,因为它在当前情况下报告错误?为什么ifort考虑 str1%arrayofint成为 Intent(in) ,好像 str1Type(STRUCT1), Intent(in)而不是 Type(STRUCT1), Pointer, Intent(in) ?正在引入指针的本地副本,如 LOC_extendthird() 所示缓解问题的最合适方法是什么?

最佳答案

对于指针虚拟参数,intent(in)属性意味着指针不应出现在所谓的指针关联上下文中。松散地说,这意味着您不能(可能)更改虚拟参数的指针关联。您可以更改此指针的目标值。

对于指针虚拟参数,intent(in)属性不会“级联”到参数的子对象(例如本例中的组件 arrayofint ):组件 arrayofint目标的str1没有 intent(in)属性。

在类似 str1%arrayofint 的引用中与 str1一个指针,这是对组件的引用 arrayofint目标的str1 .即使intent(in)属性确实适用于指针虚拟参数的子对象str1%arrayofint 引用的对象不是 str1 的子对象.

如果认为这样的对象具有 intent(in) 是错误的。属性。您已经找到了一种有效的方法来解决此类缺陷。您应该考虑将此缺陷报告给英特尔。

最后,可能有更好的方法来解决您在不使用指针虚拟参数的情况下调整组件大小的问题,但我不会在这个答案中考虑这些。

关于pointers - Ifort : move_alloc() on attribute of a Pointer, intent(in) 触发错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59967858/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com