I am facing an issue with ifort 17.0 (the same code was working fine with ifort 12.1 and 16.0) on a simple code where I try to deallocate the fptr returned by C_F_POINTER from ISO_C_BINDING (I associate there the pointer to a C allocated array of char). The error on program compiled with ifort 17.0 is:
forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Here is the snippet of code:
program testalloc use ISO_C_BINDING implicit none interface function c_alloc(buf) bind(C,name="alloc_in_c") use ISO_C_BINDING integer(C_INT) :: c_alloc type(C_PTR), intent(out) :: buf end function c_alloc end interface type(C_PTR) :: cptr character, dimension(:), pointer :: fptr character(128) :: s integer :: len, i len = c_alloc(cptr) call C_F_POINTER(cptr, fptr, (/len/)) s = ' ' do i=1,len s(i:i) = fptr(i) end do print *,"obtained string = ",TRIM(s) if (associated(fptr)) then deallocate(fptr) end if end program testalloc
As no error was detected with previous version of the compiler, I was wondering if it could be a bug in this 17.0 version or if my code was simply not valid but that was not detected/enforced previously?
Patient: Doctor, it hurts when I do this!
Doctor: Then don't do that!
Your code is not legal. You must not DEALLOCATE a pointer that wasn't allocated through Fortran ALLOCATE. (This could be through a call to CFI_allocate when using a C descriptor in C, but you're not doing that.) Furthermore, the pointer you get with C_F_POINTER is generally not valid for use with DEALLOCATE,
That the program appeared to work in an earlier compiler version is not an indication of a bug in the newer version.
Ah! Thanks Doctor for pointing this out :-)
So if I understand correctly, the only valid way to free this memory from Fortran is by calling a C function to do so on the C_PTR 'cptr' right?
Just to make sure: in case I want to do this in a bloc where I do not have a reference to the initial C_PTR anymore but only the associated Fortran pointer, will a call to C_LOC(fptr) give me the exact same C_PTR which I can then pass to a C free function?
Be careful. Someone (even you) may change the code later to have fptr point to a Fortran allocated object. The safest route may be to preserve the INTEGER(C_PTR) value and to insert debug code (in debug build) to assert the equivalence. And to null out both copies after deallocation.
As Jim suggests, as long as you don't change the pointer assignment, C_LOC should work. You may want to look into the F2015 C interoperability features that Intel Fortran now supports. This adds the ability to share Fortran pointers and allocatables with C.
Thanks for the tips, I'll make sure to be careful when manipulating this fptr (due to complexity of the code and use-cases, it might involve adding a marker to specify whether the data comes from the C library or was directly allocated in Fortran).
Concerning the new F2015 C interoperability features, sharing Fortran pointers and allocatables with C sounds great to have but will not help in my case, as my C library is common not only to Fortran code but also to other programming languages (Python, Java, C++ to name a few).
An esoterically question.
Assume the allocation is performed in C. Assume the object allocated is an array of reals. Assume, C_F_POINTER is used to properly construct an array descriptor for the pointer.
Now: fptr = LargerArrayOfReals
Where realloc lhs is enabled?
IOW, does the array descriptor for pointer contain a flag that indicates if realloc_lhs is permitted or not permitted?
>>This is a pointer, not allocatable. realloc_lhs does not apply
Good to know. i.e. in situations where you expressly do not want to permit reallocation, you can use a pointer as opposed to an allocatable.
I would not recommend that. Instead, use:
A(:) = whatever
As I describe here, the (:) disables automatic reallocation, though of course it's now up to you to make sure that the shapes match, just as with pointers. If you make a mistake, it may not get detected by bounds checking.
The limitation on deallocating an fptr that was allocated in Fortran has proved challenging for my use case (Fortran allocatable array wrapped by Python/ctypes/NumPy). I see from the discussion a mention of Fortran 2015 C interoperability for sharing allocatables. I could not track down the documentation for this capability. Could you please point me in the right direction? Thank you!