Fortran ISO_C_BINDING C_F_POINTER C memory ownership at the C-Fortran boundary
0 reputation · 01 Feb 2021, 16:10 UTC
0 reputation · 01 Feb 2021, 16:10 UTC
Goal: expose a C-allocated object to Fortran using C_F_POINTER and determine which language owns the memory and when the Fortran pointer becomes invalid.
ISO_C_BINDING states that C_F_POINTER does not transfer ownership or finalization, and access after the C object is freed is undefined behavior. Derived types with allocatable or pointer components are not interoperable with C, so layout and lifetime depend on the compiler, ABI, and standard mode. The deallocation boundary is therefore not fixed by the language standard alone.
What deallocation sequence keeps the Fortran pointer valid until the final access? Is it safe for Fortran to request C free through a BIND(C) procedure, or must C retain lifetime control? Must the C allocator outlive every Fortran reference in standard-conforming code?
35275 reputation · 02 Feb 2021, 02:39 UTC
C retains ownership of the memory. The Fortran pointer associated via C_F_POINTER is valid only while the C allocation lives. The standard-conforming deallocation sequence is: C allocates → Fortran uses pointer via C_F_POINTER → Fortran signals completion → C frees. Reversing this order (C frees while Fortran still holds references) is undefined behavior. Fortran may call a BIND(C) free function, but only after the last Fortran reference; C must retain lifetime control in standard-conforming code.
C_F_POINTER (Fortran 2018, 18.2.3) associates a Fortran pointer with a C address but does not transfer allocation status, finalization responsibility, or ownership.DEALLOCATE or finalizer can release C-allocated memory; only the matching C deallocator (free, custom destroy) may do so.ASSOCIATED limitation: ASSOCIATED(ptr) returns true even after C free; it does not detect invalidation.The standard deliberately leaves lifetime management to the programmer because C and Fortran have different memory models. The C allocator must outlive every Fortran reference in standard-conforming code. A typical safe pattern:
malloc (or a matching allocator) and passes the address to Fortran.C_F_POINTER(cptr, fptr) to associate a Fortran pointer.fptr.free (or its destroy function) after step 4.If Fortran must request deallocation, expose a BIND(C) procedure that Fortran calls to notify C; C then frees. Do not call free directly from Fortran on a pointer that Fortran still references.
BIND(C) on the Fortran derived type.malloc/calloc/aligned_alloc (or a documented C API allocator).C_F_POINTER.What C allocator is used? If it is not malloc/free (e.g., a pool allocator, mmap, C++ new, or a custom arena), the matching deallocator must be called from C, and the same lifetime rule applies. This changes the recommendation only if the allocator/deallocator pair is mismatched.
-std=f2018 -Wall -Wextra (gfortran, ifort, nvfortran, flang).-fsanitize=address) or Valgrind to catch use-after-free across the boundary.malloc → C_F_POINTER → Fortran read/write → C free → Fortran read (should trigger ASan/Valgrind).Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.