繁体   English   中英

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

[英]Pointer is being being masked when calling a C function from Fortran

TL; 博士

当我将一个数组从 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_函数,并检查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 ,但行为(崩溃)保持不变。

这是我的主要评论 [和你的] 的序言。

您似乎收到了地址的 [不需要的] 标志扩展名。

gfortran是用-mcmodel=medium构建的,但 C 没有。

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

因此,将选项添加到两者或将其都保留以解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM