with c_f_pointer is fortran array reshape in-place or not

时光毁灭记忆、已成空白 提交于 2020-01-02 09:11:56

问题


I have a question related to one asked some years ago on Intel Developer Forum about the in-place reshaping of an array.

In short, the answer was that an array of a certain rank can be allocated, and a pointer created that refers to the same memory location (i.e. in-place), but with a different rank, e.g.:

use, intrinsic :: ISO_C_BINDING
integer, allocatable, target :: rank1_array(:)
integer, pointer :: rank3_array(:,:,:)
integer :: i

! Allocate rank1_array 
allocate(rank1_array(24))

! Created rank3_pointer to rank1_array
call C_F_POINTER (C_LOC(rank1_array), rank3_array, [3,2,4])

! Now rank3_array is the same data as rank1_array, but a 3-dimension array with bounds (3,2,4)

My question is now that if I deallocate the original array rank1_array, why is it that the pointer rank3_array is still associated, and can be used without a problem (seemingly). Thus, if I append the code segment from above with:

! initialise the allocated array
rank1_array = [(i, i=1,24)]

! then deallocate it
deallocate(rank1_array)

! now do stuff with the pointer
print *, associated(rank3_array)
rank3_array(2,2,1) = 99
print *, rank3_array

Compiling and running this program gives me the output

gfortran -Wall my_reshape.f90 -o my_reshape
./my_reshape
T
1 2 3 4 99 6 7 ... 23 24

If the memory of rank1_array was deallocated, why does rank3_array still function unless it is a copy of the original? Was the initial reshape then in-place or not? Would be very grateful if someone could explain this behaviour to me.

I'm using gfortran 6.1.0 of that is of interest.

Edit/Update:

As the accepted answer by @francescalus indicates, the real issue here is how I (incorrectly!) handled pointers in general and not the in-place reshape with C_F_POINTER in particular. The strange behaviour I saw was just a result of undefined behaviour due to non-compliant fortran code I wrote. Based on @francescalus answer and comments, I did more reading online and thought it might be useful to give a link to a relevant section of a Fortran Reference Manual that very clearly explains how pointers and allocatable arrays should be handled.


回答1:


That c_f_pointer is used instead of "normal" pointer assignment is not relevant to the problem, nor is the changing shape.

After the call to c_f_pointer the pointer rank3_array is pointer associated with the target rank1_array. There is no copy made.

When rank1_array is deallocated in the statement

 deallocate(rank1_array)

this has an effect on the pointer which has rank1_array as a target. In particular, the pointer association status of rank3_array becomes undefined. (Whenever a pointer's target is deallocated except through the pointer, the pointer's association status becomes undefined.)

With the pointer of undefined association status the next part

print *, associated(rank3_array)

is not allowed. At this point the program is not a Fortran-compliant program (and the compiler needn't detect that) and the processor is allowed to print .TRUE. here if it wants to.

Equally, with

rank3_array(2,2,1) = 99
print *, rank3_array

rank3_array itself is undefined and those references are also not allowed. Again, any effect is available to the compiler.

Now, as in another answer on a similar topic: just because rank1_array has been deallocated that doesn't mean that the memory gets purged. Probably all that happens is some array descriptor for the first array has its status changed. It isn't the compiler's responsibility to do the same to all related pointers/descriptors. (And so the pointer's descriptor may indeed still say "associated".)

It's important to note, though: it may look like it's working, but I wouldn't advise betting your job on it.



来源:https://stackoverflow.com/questions/44446539/with-c-f-pointer-is-fortran-array-reshape-in-place-or-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!