次の単純なプログラムで、派生型の割り当て可能な配列メンバーでセグメンテーション違反が発生しました。このセグメンテーション違反は、1 台のマシン (openSUSE で Intel Fortran 14.0.3 を使用) でのみ発生し、別のマシン (Ubuntu で Intel Fortran 14.0.2 を使用) では発生しませんでした。また、プログラム内の整数パラメータの 1 つを変更すると、プログラムは正常に終了します。
誰でも問題を再現できますか?コードの何が問題なのか誰か教えてもらえますか?
以下に、3 つのソース コード ファイルを示します。
main_dbg.f90
.. セグメンテーション違反が発生するかどうかは、このファイルのn1
との値に依存します。n2
PROGRAM dbg
USE tktype
USE mymodule, ONLY : MyClass, MyClass_constructor
IMPLICIT NONE
INTEGER(I4B) :: n1,n2,n3
TYPE(MyClass) :: o_MyClass
n1=23
n2=32
! .. this does not work.
! n2=31
! .. this works.
n3 = n1*n2
write(*,'(1X,A,I10)') 'n1=', n1
write(*,'(1X,A,I10)') 'n2=', n2
write(*,'(1X,A,I10)') 'n3=', n3
o_MyClass = MyClass_constructor(n1, n2, n3)
call o_MyClass%destructor()
write(*,*) '***************************'
write(*,*) ' Normal End :) '
write(*,*) '***************************'
END PROGRAM dbg
strange.f90
forall
..このファイルのコンストラクトで
セグメンテーション違反が発生します。
!*******************************************************************
MODULE mymodule
!*******************************************************************
USE tktype
IMPLICIT NONE
PRIVATE
PUBLIC MyClass
PUBLIC MyClass_constructor
TYPE :: MyClass
PRIVATE
REAL(DP), DIMENSION(:), ALLOCATABLE :: arrA
COMPLEX(DPC), DIMENSION(:,:,:), ALLOCATABLE :: arrB
CONTAINS
PROCEDURE :: destructor
END TYPE MyClass
! ================================================================
CONTAINS
! ================================================================
! ****************************************************************
FUNCTION MyClass_constructor(n1, n2, n3) RESULT(this)
! ****************************************************************
TYPE(MyClass) :: this
INTEGER(I4B), INTENT(IN) :: n1, n2, n3
! local variables
INTEGER(I4B) :: j1, j2, j3
write(*,'(1X,A)') 'entered constructor..'
allocate(this%arrA(n2))
allocate(this%arrB(n1, n2, n3))
this%arrA = 1.0_dp
write(*,*) 'size(this%arrB,1) =', size(this%arrB,1)
write(*,*) 'n1 = ', n1
write(*,*) 'size(this%arrB,2) =', size(this%arrB,2)
write(*,*) 'n2 = ', n2
write(*,*) 'size(this%arrB,3) =', size(this%arrB,3)
write(*,*) 'n3 = ', n3
forall(j1=1:n1, j2=1:n2, j3=1:n3)
this%arrB(j1,j2,j3) = this%arrA(j2)
end forall
write(*,'(1X,A)') '..leaving constructor'
END FUNCTION MyClass_constructor
! ****************************************************************
SUBROUTINE destructor(this)
! ****************************************************************
CLASS(MyClass), INTENT(INOUT) :: this
deallocate(this%arrA)
deallocate(this%arrB)
END SUBROUTINE destructor
END MODULE mymodule
tktype.f90
! ********************************************************************
MODULE tktype
! ********************************************************************
! module tktype is an extraction of module nrtype in Numerical Recipes in
! Fortran 90.
! ********************************************************************
! Symbolic names for kind types of 4-, 2-, and 1-byte integers:
INTEGER, PARAMETER :: I4B = SELECTED_INT_KIND(9)
INTEGER, PARAMETER :: I2B = SELECTED_INT_KIND(4)
INTEGER, PARAMETER :: I1B = SELECTED_INT_KIND(2)
! Symbolic names for kind types of single- and double-precision reals:
INTEGER, PARAMETER :: SP = KIND(1.0)
INTEGER, PARAMETER :: DP = KIND(1.0D0)
! Symbolic names for kind types of single- and double-precision complex:
INTEGER, PARAMETER :: SPC = KIND((1.0,1.0))
INTEGER, PARAMETER :: DPC = KIND((1.0D0,1.0D0))
! Symbolic name for kind type of default logical:
INTEGER, PARAMETER :: LGT = KIND(.true.)
END MODULE tktype
以下は、上記のソース コードをコンパイルし、生成された実行可能ファイルを実行するためのシェル スクリプトです。
compile_run.sh
#!/bin/bash
ifort -v
echo "compiling.."
ifort -o tktype.o -c -check -g -stand f03 tktype.f90
ifort -o strange.o -c -check -g -stand f03 strange.f90
ifort -o main_dbg.o -c -check -g -stand f03 main_dbg.f90
ifort -o baabaa strange.o tktype.o main_dbg.o
echo "..done"
echo "running.."
./baabaa
echo "..done"
標準出力は次のようになりました。
ifort version 14.0.3
compiling..
..done
running..
n1= 23
n2= 32
n3= 736
entered constructor..
size(this%arrB,1) = 23
n1 = 23
size(this%arrB,2) = 32
n2 = 32
size(this%arrB,3) = 736
n3 = 736
./compile_run.sh: line 11: 17096 Segmentation fault ./baabaa
..done
編集 2016-01-30
ulimit -s unlimited
の先頭 ( の後#/bin/bash
) に追加するとcompile_run.sh
、セグメンテーション違反が防止されることがわかりました
。Fortran の割り当て可能な配列は、ヒープではなくスタックに格納されていますか?