Le code suivant renvoie un défaut de segmentation car le tableau allouable que j'essaie de transmettre n'est pas correctement reconnu (la taille renvoie 1, alors qu'elle devrait être 3). Dans cette page (http://www.eng-tips.com/viewthread.cfm?qid=170599) un exemple similaire semble indiquer qu'il devrait fonctionner correctement dans F95; mon fichier de code a une extension .F90, mais j'ai essayé de le changer en F95, et j'utilise gfortran pour compiler.
Je suppose que le problème devrait être dans la façon dont je passe le tableau allouable au sous-programme; Qu'est-ce que je fais mal?
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
PROGRAM test
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
IMPLICIT NONE
DOUBLE PRECISION,ALLOCATABLE :: Array(:,:)
INTEGER :: iii,jjj
ALLOCATE(Array(3,3))
DO iii=1,3
DO jjj=1,3
Array(iii,jjj)=iii+jjj
PRINT*,Array(iii,jjj)
ENDDO
ENDDO
CALL Subtest(Array)
END PROGRAM
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
SUBROUTINE Subtest(Array)
DOUBLE PRECISION,ALLOCATABLE,INTENT(IN) :: Array(:,:)
INTEGER :: iii,jjj
PRINT*,SIZE(Array,1),SIZE(Array,2)
DO iii=1,SIZE(Array,1)
DO jjj=1,SIZE(Array,2)
PRINT*,Array(iii,jjj)
ENDDO
ENDDO
END SUBROUTINE
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
Si une procédure a un argument factice qui peut être alloué, une interface explicite est requise dans toute étendue appelante.
(Il existe de nombreuses choses qui nécessitent une interface explicite, un mannequin attribuable n'en est qu'un.)
Vous pouvez fournir cette interface explicite vous-même en plaçant un bloc d'interface pour votre sous-programme dans le programme principal. Une alternative et beaucoup, beaucoup, beaucoup mieux est de mettre le sous-programme à l'intérieur d'un module puis d'utiliser ce module dans le programme principal - l'interface explicite est alors automatiquement créée. Il y a un exemple de cela sur le site eng-tips auquel vous avez fourni un lien - voir le message de xwb.
Notez qu'il est logique qu'un argument factice ait l'attribut allocatable si vous allez faire quelque chose en rapport avec son statut d'allocation - interroger son statut, le réallouer, le désallouer, etc.
Veuillez également noter que votre argument factice affectable array
est déclaré avec intent(in)
, ce qui signifie que son statut d'allocation sera celui de l'argument réel associé (et il ne peut pas être modifié pendant la procédure). L'argument réel transmis à votre sous-routine peut être non alloué et donc illégal à référencer, même avec une interface explicite. Le compilateur ne le saura pas et le comportement des requêtes comme size
n'est pas défini dans de tels cas.
Par conséquent, vous devez d'abord vérifier l'état d'allocation de array
avec allocated(array)
avant de référencer son contenu. Je suggérerais en outre d'implémenter des boucles sur le tableau complet avec lbound
et ubound
, car en général, vous ne pouvez pas être sûr des limites de array
:
subroutine subtest(array)
double precision, allocatable, intent(in) :: array(:,:)
integer :: iii, jjj
if(allocated(array)) then
print*, size(array, 1), size(array, 2)
do iii = lbound(array, 1), ubound(array, 1)
do jjj = lbound(array, 2), ubound(array, 2)
print*, array(iii,jjj)
enddo
enddo
endif
end subroutine
Il s'agit d'un exemple simple qui utilise des arguments factices allouables avec un module.
module arrayMod
real,dimension(:,:),allocatable :: theArray
end module arrayMod
program test
use arrayMod
implicit none
interface
subroutine arraySub
end subroutine arraySub
end interface
write(*,*) allocated(theArray)
call arraySub
write(*,*) allocated(theArray)
end program test
subroutine arraySub
use arrayMod
write(*,*) 'Inside arraySub()'
allocate(theArray(3,2))
end subroutine arraySub