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

C calls Fortran - CFI_deallocate returns Error Code 6

Ibrahim_K_
New Contributor I
601 Views

I am investigating the C++ and Fortarn inetroperability features. I was playing with the sample code (came with the Fortran compiler) which demonstrates C++ and Fortran interoperability. I included the following statements at the end of the CPP file:

irc1 = CFI_deallocate((CFI_cdesc_t *)&instring_desc);
irc2 = CFI_deallocate((CFI_cdesc_t *)&outstring_desc);
cout << "irc1=" << irc1;
cout << "irc2=" << irc2;

I get return codes 6 in both calls. You will recall that the Fortran descriptors were allocated with:

status = CFI_establish(...)

I have the following questions:

1) The sample code does not do it, but is it not good practice to do so (deallocate) to prevent memory leaks?

2) What is the difference between CFI_allocate and CF_establish?

3) I cannot find the error codes returned from CFI_allocate, CFI_establish, and CFI_deallocate. What does error code 6 mean?

Thanks for any clarification in advance,

I. Konuk

 

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
601 Views

Yes, that's mostly correct. The part that isn't quite is your reference to CFI_CDESC_T(0) as a "call". It's a macro that expands to a struct declaration for a CFI_cdesc_t type with zero dimensions (a scalar). It only allocates space for the descriptor - nothing is filled in until you call CFI_establish.So it doesn't have the address of anything until CFI_establish.

The C interoperability features, especially the new ones in F2018, are among my favorites in the language.

View solution in original post

0 Kudos
4 Replies
Steve_Lionel
Honored Contributor III
601 Views

All of the error codes are defined in ISO_Fortran_binding.h. Error 6 is CFI_INVALID_ATTRIBUTE - the reason you got this was that you attempted to deallocate a "CFI_attribute_other" (not allocatable or pointer) entity.

CFI_establish fills in a C descriptor so that it describes some bit of storage. In the C_Calls_Fortran example, this is done for the char variables instring and outstring, both of which have storage created by the C main program, not through a Fortran allocation, so it is inappropriate to deallocate them.

You need to use CFI_establish if you construct the descriptor in C code. If the thing was passed to you from Fortran (where the standard specifies the use of a C descriptor), then Fortran has already done this work.

CFI_allocate is the equivalent of a Fortran ALLOCATE, and is to be used only on a C descriptor that describes an allocatable or pointer variable (has attributes CFI_attribute_allocatable or CFI_attribute_pointer). CFI_deallocate is the Fortran DEALLOCATE operation. You are required to use these in C code if you want to allocate or deallocate a Fortran allocatable/pointer variable - no malloc/free allowed!

It would be good practice to deallocate variables that were allocated before the program exits, but CFI_deallocate should be used only on C descriptors for allocatable/pointer.

0 Kudos
Ibrahim_K_
New Contributor I
601 Views

Steve:

Thank you very much for a thorough explanation. In order to make sure I understand this correctly, i will restate my understanding: CFI_establish simply fills in the C descriptors in the C structure "instring_desc" created/allocated by the call:

CFI_CDESC_T(0) instring_desc, outstring_desc; // Ignore warning for zero-sized array

After this call, "instring_desc" contains the descriptor information/data along with the address of:

char instring[40];

and therefore its is declared CFI_type_char in the "CFI_establish" call.

I. Konuk

0 Kudos
Ibrahim_K_
New Contributor I
601 Views

I found a very detailed document written by Reinhold Bader of Leibniz Supercomputing Center titled "Extended interoperation with C". It more or less confirms my understanding.

Thank you again very much.

I. Konuk

0 Kudos
Steve_Lionel
Honored Contributor III
602 Views

Yes, that's mostly correct. The part that isn't quite is your reference to CFI_CDESC_T(0) as a "call". It's a macro that expands to a struct declaration for a CFI_cdesc_t type with zero dimensions (a scalar). It only allocates space for the descriptor - nothing is filled in until you call CFI_establish.So it doesn't have the address of anything until CFI_establish.

The C interoperability features, especially the new ones in F2018, are among my favorites in the language.

0 Kudos
Reply