32 ビット システムでは機能するが、64 ビット コンパイラでは警告と懸念が発生する、C 呼び出しを含む少し古い Fortran プログラムを見ています。このプログラムは、動的に割り当てられたメモリへの C ポインタのアドレスを として格納します。このメモリint
は、Fortran 側で として共有されINTEGER
ます。int
私の懸念は、64 ビット整数システムでは、C ポインターからのキャストが/として格納できるものよりも大きくなる可能性があることINTEGER
です。既存のプログラムを 2 つのファイルでこの例に簡略化しました。
フォートラン: 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
子: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 コードに修正を加える必要がありますか?