从Fortran调用C函数时,指针被屏蔽

时间:2019-01-26 04:01:22

标签: c cuda fortran

TL; DR

当我将数组从Fortran传递到C时,该数组的地址在C语言中是错误的。我已经通过在CALL之前在Fortran中打印该数组的地址,然后进入C函数并打印参数的地址。

  • Fortran指针:0x9acd44c0
  • C指针:0xffffffff9acd44c0

C指针的高位双字已设置为0xffffffff。我试图了解为什么会这样,并且只在HPC集群而不是开发计算机上发生。

上下文

我正在使用用Fortran / C ++ / CUDA编写的大型科学程序。在某些特定的计算机上,从Fortran调用C函数时遇到段错误。我发现一个指针传递给C函数的某些字节设置不正确。

代码段

程序中的每个Fortran文件都包含一个公共头文件,该头文件设置了一些选项并声明了公共块。

IMPLICIT REAL*8  (A-H,O-Z)
COMMON/NBODY/  X(3,NMAX), BODY(NMAX)
COMMON/GPU/    GPUPHI(NMAX)

Fortran呼叫站点如下:

CALL GPUPOT(NN,BODY(IFIRST),X(1,IFIRST),GPUPHI)

nvcc编译的C函数的声明如下:

extern "C" void gpupot_(int *n,
                       double m[],
                       double x[][3],
                       double pot[]);

GDB输出

通过调试,我发现指向pot的指针的值不正确;因此,任何尝试访问该阵列的尝试都会出现段错误。

使用gdb运行程序时,我在调用gpupot之前放置了一个断点,并打印了GPUPHI变量的值:

(gdb) p &GPUPHI   
$1 = (PTR TO -> ( real(kind=8) (1050000))) 0x9acd44c0 <gpu_>

然后,我让调试器进入gpupot_ C函数,并检查pot参数的值:

(gdb) p pot
$2 = (double *) 0xffffffff9acd44c0

所有其他参数都具有正确的指针值。

编译器选项

gfortran设置的编译器选项为:

 -fPIC -O3 -ffast-math -Wall -fopenmp -mcmodel=medium -march=native -mavx -m64  

nvcc正在使用以下内容:

-ccbin=g++ -Xptxas -v -ftz=true -lineinfo -D_FORCE_INLINES \
-gencode arch=compute_35,code=sm_35 \
-gencode arch=compute_35,code=compute_35 -Xcompiler \
"-O3 -fPIC -Wall -fopenmp -std=c++11 -fPIE -m64 -mavx \
-march=native" -std=c++14 -lineinfo 

对于调试,-O3-g -O0 -fcheck=all -fstack-protector -fno-omit-frame-pointer代替,但是行为(崩溃)保持不变。

1 个答案:

答案 0 :(得分:1)

这是我[和您的]最重要评论的开头。

您似乎正在获得地址的[不需要的]符号扩展名。

gfortran是用-mcmodel=medium构建的,而C不是。

使用该选项,较大的符号/数组将链接到2GB以上(已设置符号位)

因此,请将选项都添加到这两个选项中,或者都将其关闭以解决问题。