Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Deallocate error on pointer obtained through C_F_POINTER

Olivier_H_
Beginner
1,100 Views

Hi, 

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?

Thanks
Olivier

0 Kudos
10 Replies
Steve_Lionel
Honored Contributor III
1,101 Views

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.

0 Kudos
Olivier_H_
Beginner
1,101 Views

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?

Thanks
Olivier

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,101 Views

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.

Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
1,101 Views

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.

0 Kudos
Olivier_H_
Beginner
1,101 Views

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).

Olivier

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,101 Views

Steve,

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?

Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
1,101 Views

This is a pointer, not allocatable. realloc_lhs does not apply.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,101 Views

>>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.

Jim Dempsey

0 Kudos
Steve_Lionel
Honored Contributor III
1,101 Views

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.

0 Kudos
Koziol__Ben
Beginner
1,101 Views

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!

0 Kudos
Reply