我正在查看一个稍旧的 Fortran 程序,它带有适用于 32 位系统的 C 调用,但会引发对 64 位编译器的警告和担忧。该程序将指向动态分配内存的 C 指针的地址存储为int
,在 Fortran 端共享为INTEGER
。我担心的是,在 64 位整数系统上,来自 C 指针的转换可能大于可以存储为int
/的值INTEGER
。我已经使用两个文件将现有程序简化为这个示例。
Fortran: this.f
program this
integer,pointer :: iptr
allocate(iptr)
call that_allocate(iptr)
write(*,'(A, Z12)') 'Fortran: iptr address', iptr
call that_assemble(iptr)
call that_free(iptr)
end program this
C:that.c
#include <stdlib.h>
#include <stdio.h>
typedef struct data {
int a;
float b;
} data;
void that_allocate_(int* iptr)
{
data *pData = calloc(1, sizeof(data));
*iptr = (int)pData;
printf("C: Allocated address %p (or %d)\n", pData, pData);
return;
}
void that_assemble_(int* iptr)
{
data *pData = (data *) *iptr;
pData->a = 42;
pData->b = 3.1415926;
return;
}
void that_free_(int* iptr)
{
data *pData = (data *) *iptr;
printf("C: Freeing data %d and %g at %p\n", pData->a, pData->b, pData);
free(pData);
return;
}
编译
-m32
该程序可以使用32 位(这里没有问题)和-m64
64 位的 GNU 编译器进行编译。编译 C 代码会引发一些警告:
$ gcc -m64 -c that.c
that.c: In function ‘that_allocate_’:
that.c:12: warning: cast from pointer to integer of different size
that.c: In function ‘that_assemble_’:
that.c:19: warning: cast to pointer from integer of different size
that.c: In function ‘that_free_’:
that.c:27: warning: cast to pointer from integer of different size
而其余的编译和链接都很好,并且程序可以正常工作:
$ gfortran -m64 -o prog this.f that.o
$ ./prog
C: Allocated address 0x1130b40 (or 18025280)
Fortran: iptr address 1130B40
C: Freeing data 42 and 3.14159 at 0x1130b40
问题
虽然我看到calloc
返回的地址可以满足 4 字节整数的数据限制,但是否存在calloc
返回更大整数地址的风险?强制转换(intptr_t)
将使编译警告静音,但我怀疑如果尝试将指针强制转换为截断地址,它将截断任何更高位和“分段错误”。它是否正确?
我该怎么办?修复需要在 Fortran 代码上进行吗?