Ifort:指针属性的move_alloc(),intent(in)触发错误

问题描述 投票:1回答:1

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

Pointer, Intent(in)

其中Type(STRUCT1), Pointer, Intent(in) :: str1 ... call MOVE_ALLOC(TO= str1%arrayofint , FROM= temparray) 是指向结构的指针,str1是要扩展的属性。请参见以下示例代码的子例程arrayofint编译器ifort返回以下错误:

LOC_extendsecond()

好像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)str1,指向结构Intent(in)的属性是否应视为str1%arrayofint

为了调查此问题,我尝试不使用Intent(in),发现在例程中取消分配或分配MOVE_AllOC()不会触发ifort的任何错误或警告。请参见示例代码的子例程str1%arrayofint

[我的一个同事提出了一种解决方法(感谢Luc!):创建了指针的本地副本,并且可以使用该指针的本地副本调用LOC_extendfirst(),而不会因ifort引发错误。请参见示例代码的子例程MOVE_AllOC()

LOC_extendthird()

这里是示例代码:

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

在Windows上使用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 调用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不会导致任何错误:它仅显示有关未使用功能的警告。

关于Fortran,我是一个新手。我知道Fortran指针比C指针包装更多的数据,所以我想知道修改属性gfortran -c Source1.f90 -Wall是否正确,因为str1%arrayofintstr1,就像在函数中修改str1-> arrayofint正确一样,是指针str1通过值传递。

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

pointers memory-management compiler-errors fortran
1个回答
0
投票

对于指针虚拟参数,LOC_extendthird()属性表示指针不应出现在所谓的指针关联上下文中。松散地,这意味着不允许您(潜在地)更改哑元参数的指针关联。您可以更改此指针的目标值。

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

在类似intent(in)的引用中带有str1%arrayofint指针,这是对str1target的分量arrayofint的引用。即使str1属性确实适用于指针伪参数的子对象,由intent(in)引用的对象也不是str1%arrayofint的子对象。

[认为这样的对象具有str1属性是错误的。您已经找到了解决ifort中此类缺点的有效方法。您应该考虑将此漏洞报告给英特尔。

最后,也许有更好的方法来解决不使用指针虚拟参数而调整组件大小的问题,但我不会在此答案中考虑这些。

© www.soinside.com 2019 - 2024. All rights reserved.