web-dev-qa-db-ja.com

Fortranコンパイルエラー-未定義の参照

たくさんのモジュールを使用するFortranプログラムをコンパイルしようとしています。コンパイルするとエラーが発生し、頭がおかしくなります。このエラーは、1つのサブルーチンの追加によって発生し、プログラムを再コンパイルしようとすると発生します。

メインプログラムには、次の2行が含まれています。

-

call read_step(nStepOne,molOne)
call read_step(nStep,mol)

-

これは、ファイル「fileio.f90」内のサブルーチンの1つを呼び出しています。

-

subroutine read_step(n,tape)

implicit none

integer, intent(in) :: tape
integer, intent(out) :: n

character(len=6) :: dum

rewind(tape)
read (tape,*)
read (tape,*) dum, n
rewind(tape)
return
!
end subroutine read_step

-

コンパイルしようとすると、次のエラーが発生します。

ifort -o SpIdMD.x *.o -static-intel -openmp 
SpIdMD.o: In function `MAIN__':
SpIdMD.f90:(.text+0x3b2): undefined reference to `read_step_'
SpIdMD.f90:(.text+0x3c5): undefined reference to `read_step_'
make: *** [SpIdMD.x] Error 1

同じモジュール内の他のサブルーチンの呼び出しではエラーは発生せず、「古いサブルーチン」の呼び出しと作成したばかりのサブルーチンの呼び出しに違いは見られません。

これらの「古いサブルーチン」の1つで、文句を言わない例は次のとおりです。

メインプログラムでは:

call get_dim(n_atom,nSnap,mol)

Fileio.f90の場合:

subroutine get_dim(n,n_snap,tape)

implicit none

integer,intent(in) :: tape
integer,intent(out) :: n, n_snap
integer :: m

rewind(tape)
read (tape,*,err=1,end=2) n
rewind(tape)

m = 0
do while (.true.)
   read (tape,*,err=1,end=3)
   m = m +1
end do
3   n_snap = m/(n + 2)
if (m.ne.(n_snap*(n + 2))) stop  'unexpected end of input file'

rewind(tape)

return
!
1   stop 'error in input file'
2   stop 'unexpected end of input file'
end subroutine get_dim

なぜこの振る舞いをするのか全くわかりません。誰かが私がこの悪夢を解決するのを手伝ってくれるなら、私は感謝するでしょう。ありがとう!

8
user2296052

サブルーチンread_stepの定義がモジュール内にある場合は、そのモジュールのUSEステートメントをメインプログラムの先頭に追加するのを忘れているか、モジュール内の関連するプロシージャがPUBLICではありません。

そのコンパイラ(および他のいくつか)では、モジュールプロシージャのリンカ名は通常、モジュール名の後に 'mp'(大文字と小文字が異なる場合があります)の後にプロシージャ名が続き、さまざまな量の先頭と末尾の下線が付いています。味に塩漬け。リンカエラーにはその「マングリング」がありません。これは、スコープをプロシージャ参照でコンパイルするときに、コンパイラがプロシージャがモジュールプロシージャであると見なさないことを示します。

8
IanH

より具体的には、他の回答で言及されているUSEステートメントとPUBLICステートメントの使用方法を示します。

F77関数を次のようにラップしました。

_  module mod
  contains
  FUNCTION FUNC(PARAM)
  ...
  END
  end module mod
_

古いコード(1986)は大文字であり、私のコードは小文字です。これは正常にコンパイルされます。 modulecontainsの間に_public func_を追加できます。しかし、これはデフォルトのようですので、あなたはそれを必要としません。

リンクするときは、次のようにプログラムとライブラリを渡す必要があります:_gfortran -o prog prog.for mod.for_(または以前にコンパイルされた場合は_.o_)。

0
JPT