- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The following code compiles using ifort, but then fails at the deallocate statement :
program fort_tst
use iso_c_binding
INTEGER, POINTER :: a(:)
TYPE(C_PTR) :: ptr
INTEGER, POINTER :: b(:)
ALLOCATE(a(5))
ptr = c_loc(a)
CALL c_f_pointer(ptr,b,[5])
DEALLOCATE(b)
end program fort_tst
The error is :
forrtl: severe (173): A pointer passed to DEALLOCATE points to an object that cannot be deallocated
Image PC Routine Line Source
fort_tst 000000000040C5A1 Unknown Unknown Unknown
fort_tst 0000000000403A17 Unknown Unknown Unknown
fort_tst 0000000000403812 Unknown Unknown Unknown
libc-2.17.so 00002AAAAB20F555 __libc_start_main Unknown Unknown
fort_tst 0000000000403729 Unknown Unknown Unknown
The pointer `b` in the code above has a proper internal array descriptor, and can be used as an alias to the array `a` in all cases, it seems, with the one exception that `b` cannot be deallocated.
From the Intel Compiler Guide on c_f_pointer , the Intel behavior is a design choice :
Since the resulting data pointer fptr could point to a target that was not allocated with an ALLOCATE statement, fptr cannot be freed with a DEALLOCATE statement.
This restriction limits some really basic use cases, especially when writing wrappers for legacy Fortran code.
Example : A Fortran subroutine S1 allocates an array. A pointer to this array is stored by C wrapper for later referencing. A second Fortran subroutine S2 is called to de-allocate the array (passed in as C pointer stored by wrapper) when it is no longer needed.
A potential solution is to allocate all memory in C. But this could require substantial code re-write, especially is a large number of arrays must be managed.
Is there any chance that this restriction can be relaxed in future versions?
Note: The same code, compiled using gfortran, runs to completion.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't quite understand your real world usage case properly to make suggestions but I think the Intel behaviour is standard conforming.
What are you expecting, are you expecting A to be allocated after deallocate(B) of not? Deallocate makes the memory available for reuse but something else is using that memory that the compiler may not be able to know about at the point of deallocate. Consider the case below. The whole point of C_LOC/c_f_pointer is communication between languages where the is no exchange of data attributes.
subroutine fort_tst()
use iso_c_binding
INTEGER, POINTER :: a(:)
!TYPE(C_PTR) :: ptr
INTEGER, POINTER :: b(:)
ALLOCATE(a(5))
!ptr = c_loc(a)
!CALL c_f_pointer(ptr,b,[5])
b => a
DEALLOCATE(b) ! deallocates B but not A
end subroutine fort_tst
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would like to be able to allocate a pointer in subroutine A, assign the pointer to a C pointer and store it in a C wrapper code, and once it is no longer needed, de-allocate it in subroutine B, using the stored C-pointer. The idea is to reuse the fortran code to allocate several arrays (using the same allocate statement), and store the pointers to these arrays in the C-wrapper code. So at any one time, the fortran code only knows about one of the arrays it has allocated. This is a very successful approach to reuse legacy code in a minimally invasive manner.
I realize this isn't without risk - one needs to know what they are doing.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think the current Intel implementation is lazy and not really meeting the letter of the standard where it refers to "the whole of an object that was created by allocation". Intel is taking a shortcut by setting a flag in the pointer descriptor saying that deallocation is prohibited. I understand that this is attractive, but it misses valid use cases that are standard-conforming.
I complained about this while I was still at Intel, but it's not astonishing that it was considered very low priority, since fixing it adds complication.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It does seem that odd that `b` can be used in place of `a` (just like in C) in all places, except for deallocation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My thinking may be wrong but IMO when you make a c_ptr using c_loc all you get is a handle to a memory address, you have no knowledge of what is stored there. When the programmer creates a fortran pointer using C_F_POINTER you define what is at the memory location. Is the compiler meant to track what other unrelated entities my use that address? Could it always do that in a sensible way anyway, I think not.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That thought did occur to me - that `ptr = c_loc(a)` loses information stored in the array descriptor. And so then `b` is not equivalent to `a`. Without being able to read the array descriptor, though, it is hard to know.
On the other hand, `b` can be used in all contexts that `a` can be used in, e.g. `size`, `lbound`, `ubound` all work on `b` as expected. Furthermore, at least in gfortran, DEALLLOCATE knows exactly what to deallocate, even if a bogus shape argument is passed to `c_f_pointer`, e.g. `c_f_pointer(ptr, b, [100])`. So information about `a` is clearly being passed on to `b`. The question is, why does Intel decide not to allow deallocation of `b`?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You have defined b with c_F_pointer so the compiler knows about b. The C_PTR however could be passed into an external routine that the compiler cannot see or have knowledge of. How could that routine know what the C_PTR was pointing at to deallocate it, remember C_PTR deliberately has no descriptors to allow interchange with other languages. There are some cases where the compiler could do it and some where it can't. Your use of C_LOC it in your example is to trick the compiler.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I agree - it does seem like that the c-ptr couldn't possibly have information about the original array a. But then why does it work at all wth gfortran? I have written wrappers for fairly large fortran codes using this idea and it works flawlessly in gfortran.
I posted a workaround, or solution (which may even be better than what I was trying above) on Stack Exchange :
https://stackoverflow.com/questions/70922893/deallocating-arrays-defined-from-c-f-pointer/70965432#70965432
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The memory allocator knows what it allocated. One common implementation is to allocate some extra storage that ends up before the returned pointer address to keep track of this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If I understand what you are saying, there is no fundamental reason why Intel couldn't do what Gfortran does. Is that right? And it must be the case the at something is stored at the address, because this C-ptr can be used to reference the array, set values, etc. And it would only be able to do this is it knew something about the stride, etc.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Correct - there is no fundamental reason., but it would be a significant amount of rework for what is, truthfully, a rare edge case, and would hurt performance.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page