Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29274 Discussions

Access violation problem with assumed-shape passing arrays when keeping subroutine in another file

GoldenRetriever
Beginner
1,082 Views
Hi there,
I got this problem but could not figure out the reason for it.Please find the copy of the source pasted at the end of this post for reference.
When I save the subroutine in a separate file as attached, the program can run at the first build. Then if I rebuild it, it ends up with the errors "Access violation"; when I check the passing arrays (MA, MB), their values become undefined.
To make it run again, I use the bellow 3 temporary solutions:
Solution 1: I have to play around with enable/disable betweenINCLUDE 'link_fnl_static.h' andINCLUDE 'link_fnl_shared.h' and re-run it. It works
Solution 2: Moving the subroutine back in the same file with the main program, it works fine without any trouble.
Solution 3: I also realise that if I use explicit-shape instead ofassumed-shape when passing arrays that also can remove problem.
Hope the above description is clear enough. If any of you have any suggestion for it please advise.
Thanks n Cheers
**************SOURCE*******************
Program Test_InputData
INCLUDE 'link_fnl_static.h'
! INCLUDE 'link_fnl_shared.h'
!DEC$ OBJCOMMENT LIB:'libiomp5md.lib'
IMPLICIT NONE
INTEGER LDA, LDB, N
PARAMETER (N=3, LDA=N, LDB=N)
REAL MA(LDA,N), MB(LDB,N)
DATA MA/1.0, -10.0, 5.0, 0.5, 2.0, 1.0, 0.0, 0.0, 0.5/
DATA MB/0.5, 3.0, 4.0, 0.0, 3.0, 0.5, 0.0, 0.0, 1.0/
CALL Test_InputData_SUB(N,MA,MB)
END PROGRAM Test_InputData
!------------------------------------------------------
SUBROUTINE Test_InputData_SUB(N,MA,MB)
IMPLICIT NONE
INTEGER, INTENT(IN) :: N
REAL, INTENT(IN), DIMENSION (:,:) :: MA, MB
REAL MC(N,N)
MC=MA+MB
END SUBROUTINE Test_InputData_SUB
0 Kudos
8 Replies
Steven_L_Intel1
Employee
1,082 Views
Your program is incorrect. Because the subroutine has arguments that are deferred-shape arrays, an explicit interface is required to be visible to the caller. There are several options for this, depending on the structure of your program. The ones I would recommend are either:

- Before the END PROGRAM, insert CONTAINS and then move the subroutine to following the CONTAINS
- Put the subroutine in a MODULE (following a CONTAINS) and then USE the module from the main program.
0 Kudos
GoldenRetriever
Beginner
1,082 Views
Thanks Steve, I got it now. However do you know why in my solution 1 and 2, particular solution 2 when Imoved the subroutine at the end of the main program (in the same file), it still can run? (of course the compiler gives warning of passing assumed shape array..)
As I have different large subroutines in my program so I prefer to keep them in separated files instead of inside a MODULE. If that is the case then is usingexplicit-shape arraythe only option?
0 Kudos
Steven_L_Intel1
Employee
1,082 Views
It should not matter which file the subroutine is in. In the past I have seen compiler bugs where enabling generated interface checking would mask such errors, but those get fixed as we find them.

It's up to you how you want to handle it. I would think that deferred-shape arrays would be easier to program and understand, but an explicit interface is required. You could put each of those large routines in their own module. The other way is to add an INTERFACE block visible to the caller, but I don't recommend that as it is error-prone.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,082 Views
When you use ":" in the dummy argument it means your call is passing an array descriptor (deferred shape). When you do this, then either the subroutine/function needs to be in the same compilation unit (file) or you must use an INTERFACE to the subroutine/function.

----------- explicit shape without interface -----------
[fortran]   Program Test_InputData 
    INCLUDE 'link_fnl_static.h'
!    INCLUDE 'link_fnl_shared.h'
    !DEC$ OBJCOMMENT LIB:'libiomp5md.lib'
    IMPLICIT NONE
    
    INTEGER LDA, LDB, N
    PARAMETER (N=3, LDA=N, LDB=N)
    REAL MA(LDA,N), MB(LDB,N)
    DATA MA/1.0, -10.0, 5.0, 0.5, 2.0, 1.0, 0.0, 0.0, 0.5/
    DATA MB/0.5, 3.0, 4.0, 0.0, 3.0, 0.5, 0.0, 0.0, 1.0/
    CALL Test_InputData_SUB(N,MA,MB)
    END PROGRAM Test_InputData 
    
!--------- seperate file --------------------------------------    
    SUBROUTINE Test_InputData_SUB(N,MA,MB)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: N
! *********** note use of size (n,N) **********
    REAL, INTENT(IN), DIMENSION (N,N) ::  MA, MB
    REAL MC(N,N)
    MC=MA+MB
    
    END SUBROUTINE Test_InputData_SUB
    
================ or with INTERFACE ================

   Program Test_InputData
    USE YourInterfaces    ! ******* module with your INTERFACE's
    INCLUDE 'link_fnl_static.h'
!    INCLUDE 'link_fnl_shared.h'
    !DEC$ OBJCOMMENT LIB:'libiomp5md.lib'
    IMPLICIT NONE
    INTEGER LDA, LDB, N
    PARAMETER (N=3, LDA=N, LDB=N)
    REAL MA(LDA,N), MB(LDB,N)
    DATA MA/1.0, -10.0, 5.0, 0.5, 2.0, 1.0, 0.0, 0.0, 0.5/
    DATA MB/0.5, 3.0, 4.0, 0.0, 3.0, 0.5, 0.0, 0.0, 1.0/
    CALL Test_InputData_SUB(N,MA,MB)
    END PROGRAM Test_InputData 
!--------- seperate file --------------------------------------
! YourInterfaces.f90
module YourInterfaces
    INTERFACE
      SUBROUTINE Test_InputData_SUB(N,MA,MB)
        IMPLICIT NONE
        INTEGER, INTENT(IN) :: N
        ! **** USES DEFERED SHAPE (:,:) ***
        REAL, INTENT(IN), DIMENSION (:,:) ::  MA, MB
      END SUBROUTINE Test_InputData_SUB
end module YourInterfaces
!--------- seperate file --------------------------------------    
    SUBROUTINE Test_InputData_SUB(N,MA,MB)
    USE YourInterfaces ! Assert correct interface and interfaces to other sub/func
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: N
    REAL, INTENT(IN), DIMENSION (:,:) ::  MA, MB
    REAL MC(N,N)
    MC=MA+MB
    END SUBROUTINE Test_InputData_SUB
    
[/fortran]

When you use interfaces, it is recommended that you do this by way of a module file (you can insert the interface directly into your files but then if it changes then you must make multiple edits).

Jim Dempsey
0 Kudos
Steven_L_Intel1
Employee
1,082 Views
"same file" doesn't do it. An explicit interface is required, period. This can be obtained by:

  • USEing a module that declares the procedure or being in the same module as the reference
  • Having the procedure CONTAINed in the current program unit
  • An INTERFACE block
0 Kudos
GoldenRetriever
Beginner
1,082 Views
Thanks Steve. Do agree that deferred-shape arrays make thing looks simpler.I also notice that the IMSL subroutines don't require to specify the array dimension in the caller for Fortran 90 interface; but I don't know how they did with that inside the subroutines.
Currently my program still can run but gives warnings. I will fix them with eitherexplicit-shape or explicit interfacelater on when have time for it then.
0 Kudos
GoldenRetriever
Beginner
1,082 Views
ThanksJim Dempsey. I thought it would not make any differences butin my experience, it did make difference if keeping the subrountine not in the same file. Thanks for your example, that's much easier to understand now.
0 Kudos
Steven_L_Intel1
Employee
1,082 Views
The IMSL Fortran 90 interfaces use deferred-shape array arguments, so they get the array shape automatically.
0 Kudos
Reply