仅当C_LOC地址返回到C程序时,Fortran变量需要SAVE属性? [英] SAVE attribute needed for Fortran variables when only the C_LOC address is returned to a C program?

查看:182
本文介绍了仅当C_LOC地址返回到C程序时,Fortran变量需要SAVE属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,在Fortran类型声明中使用 SAVE 属性,以便变量在子程序结束时保留其值,例如SO的答案问题此处。不过,我最近在另一个问题上给出了一个例子,说明如何编写一个只返回的Fortran函数 em> C调用程序的可分配字符串常量的C地址,具有F2003的C_LOC内部特性和其他ISO_C_BINDING特性。是否应在Fortran可分配字符串常量上使用 SAVE 属性来避免潜在问题?

尽管我没有使用 SAVE ,该函数按预期工作:C程序使用 char * 指向由Fortran函数,然后可以正常使用它(例如,用于打印并使用 strlen())。没有警告/错误产生。另外,这与编译器文档中使用的 C_F_POINTER 以及相关SO 问题(也就是说,目标值没有 SAVE attr)。特别是由于Fortran函数是从C调用的,因此我不清楚这个过程是否表现出预期的行为,或者它是否可能/应该失败,或者如果这是供应商特定的实现细节。针对 SAVE here )似乎表明一个字符串常量(可分配或不可用?)是默认保存的,但我不确定是否正在读取此权限,或者如何/如果此信息在当前上下文中存在。我是否以便携式,正确的方式执行此过程?






尽管我已经将代码链接到了代码中,但以下是重要的部分:

 ! f_string.f90:将C地址返回给一个可分配的字符串常量:
function get_string()bind(c,name ='get_string')
use,intrinsic :: iso_c_binding
implicit none
type(C_PTR):: get_string
字符(len = :),allocatable,target :: fortstring! < - 包含保存?

fortstring =Hello StackOverflow// C_NULL_CHAR! < - 以NULL结尾的字符串常量
get_string = C_LOC(fortstring)
结束函数get_string

  // c_string.c:使用char *指向'get_string'返回的地址
#include< stdio.h>
#include< string.h>
#include< stdlib.h>
char * get_string(void); //< - Fortran fcn签名
int main(){
char * mycharptr;

mycharptr = get_string();
printf(来自Fortran的字符串:%s\\\
,mycharptr);
printf(len =%d\\\
,strlen(mycharptr));
返回0;
}

编译为 ifort / c f_string.f90 icl c_string / link f_string.obj

解决方案

<这是正确的。保存是必须的。



当程序退出时,所有可分配的实体都将被释放,除非它们是 save



您可以使用指针而不是 allocatable ,并且目标不会自动解除分配。我发现它比 save 更好,因为可能会多次调用该过程。



您的程序可能工作,因为尽管内存块已被释放,但未被覆盖。所以C程序仍然可以找到有意义的数据,但是在地址上它不被允许访问。但是这种访问并不总是通过操作系统内存保护来检查。


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.

解决方案

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.

这篇关于仅当C_LOC地址返回到C程序时,Fortran变量需要SAVE属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆