SAVE attribute needed for Fortran variables when only the C_LOC address is returned to a C program?

妖精的绣舞 提交于 2020-01-03 17:49:17

问题


Normally, the SAVE attribute is used in Fortran type declarations so that the variable retains its value at the end of a subprogram, such as described by the answers to the SO question here. However, I recently gave an example at another question for how a Fortran function can be written that returns only the C address of an allocatable character string constant to a C calling program, with the C_LOC intrinsic and other ISO_C_BINDING features of F2003. Should the SAVE attribute be used on the Fortran allocatable string constant to avoid potential issues?

Although I didn't use SAVE, the function worked as intended: the C program uses a char* to point at the address returned by the Fortran function, which could then be used as normal (e.g., for printing and with strlen()). No warnings/errors were generated. Also, this seems consistent with how I have seen C_F_POINTER used in the compiler docs and the examples at a related SO question (that is, the target values did not have the SAVE attr).

Particularly since the Fortran function was called from C, it's not clear to me whether this process exhibits the expected behavior, or if it could/should have failed, or if this is a vendor-specific implementation detail. The Intel Fortran 17 documentation for SAVE (here) seems to indicate that a string constant (allocatable or not?) is saved by default, but I am not sure if I'm reading this right, or how/if this info holds up in the current context. Am I performing this process in a portable, correct manner?


Although I linked to the code already, here are the important bits:

! f_string.f90: returns the C address to an allocatable string constant:
function get_string() bind(c, name='get_string')
    use, intrinsic :: iso_c_binding
    implicit none
    type(C_PTR) :: get_string
    character(len=:), allocatable, target :: fortstring  ! <- Include SAVE?

    fortstring = "Hello StackOverflow" // C_NULL_CHAR    ! <- NULL-terminated string constant
    get_string = C_LOC(fortstring)
end function get_string

// c_string.c: uses a char* to point at the address returned by 'get_string'
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *get_string(void);                                  // <- Fortran fcn signature
int main(){
    char *mycharptr; 

    mycharptr = get_string();
    printf("String from Fortran: %s\n", mycharptr);
    printf("len = %d\n", strlen(mycharptr));
    return 0;
}

Compiled as ifort /c f_string.f90, icl c_string /link f_string.obj.


回答1:


That is correct. Save is necessary.

All allocatable entities are deallocated when the procedure exits unless they are save.

You can use pointer instead of allocatable and the target will not be automatically deallocated. I find it better than save because of possible multiple calls to the procedure.

Your program probably "worked" because although the memory block was deallocated, it was not overwritten. So the C procedure still found meaningful data, but at address it was not allowed to access. But this access is not always checked by the OS memory protection.



来源:https://stackoverflow.com/questions/44441919/save-attribute-needed-for-fortran-variables-when-only-the-c-loc-address-is-retur

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!