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

Fortran pointer error inside subroutine

shakeham
Beginner
1,207 Views

Dear all,

The following minimal code will yield to many issues with ifort 14.0.2.176 and visual studio 2013 12.0.31101.00 update 4, but I couldn't figure out what is wrong with it. It produces three issues when a structure has a member which has pointers as sub-structure. I also don't understand why it reports error when I pass the pointer inside a subroutine and declare it as pointer  (toBeCalled2). In fact, another piece of my code seems to be doing the same thing but ran into no issue. Any comment is appreciated
 

Please see inline where these occur
! issue 1: we cannot examine run_input2%test%dat1 values in visual studio
! issue 2: upon leaving the subroutine, run_input2%test%dat1 points to some junk
! issue 3: it will die inside immediately    

    ================================
          module testMod
          type test
              real*8,pointer,dimension(:):: dat1
              real*8,pointer,dimension(:,:):: dat2
          end type
          TYPE :: containsMixed
              type(test):: test
          END TYPE containsMixed
          TYPE(containsMixed) :: run_input2
          end module
    
          program main
          use testMod, Only: run_input2
          implicit none
          real*8, dimension(100),target::x
          real*8, dimension(:),pointer::p2=>null()
          x=100D0
          run_input2%test%dat1 =>  x  ! issue 1: we cannot examine run_input2%test%dat1 values in visual studio. 
          
          print*, run_input2%test%dat1(1)
          call toBeCalled(run_input2%test%dat1)
          print*, run_input2%test%dat1(1:2) ! it will produce 2, 100 which is correct
          call toBeCalled2(run_input2%test%dat1)  ! issue 2: upon leaving the subroutine, run_input2%test%dat1 points to some junk
          print*, run_input2%test%dat1(1:2) ! see junk  
           if(associated(p2)) deallocate(p2)
          call toBeCalled2(p2)  ! issue 3: it will die inside immediately
          print*, run_input2%test%dat1(1:2) ! it will produce 2, 100 which is correct
    end program
          
    subroutine toBeCalled(dat)
    real*8, dimension(*) ::dat
    dat(1)=2;
    end subroutine
          
    subroutine toBeCalled2(dat)
    ! issue 2: it will die inside
    real*8, dimension(:),pointer ::dat
    real*8, dimension(:),pointer::x2
    allocate(x2(200))
    x2 = 200
    dat=> x2;
    print*, dat(1:10)
    end subroutine

0 Kudos
7 Replies
FortranFan
Honored Contributor III
1,207 Views

When I compile your code with Intel Fortran Compiler 16.0 beta, update 2, I get the error:

error #8055: The procedure has a dummy argument that has the ALLOCATABLE,
ASYNCHRONOUS, OPTIONAL, POINTER, TARGET, VALUE or VOLATILE
attribute. Required explicit interface is missing from original source.   [DAT1]

Take a look at this blog from Dr Fortran: https://software.intel.com/en-us/blogs/2012/01/05/doctor-fortran-gets-explicit-again

Is it possible for you to provide explicit interfaces for the two procedures, tobeCalled and tobeCalled2, and retry your code?

When I do so (tobeCalled and tobeCalled2 made module procedures), the code seems to work fine with Intel Fortran Compiler 16.0 beta, update 2.

0 Kudos
shakeham
Beginner
1,207 Views

OK. #2 and #3 problem has been solved by putting the subroutines into a module. Thanks. I guess the compiler got confused what to send into the subroutine without an interface.

But #1 persists still, the debugger is not able to show the values for run_input2%test%dat1. It shows dat1 and dat2 as Undefined Address. I guess this is a bug on Intel side

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,207 Views

testMod::run_input2       is supposed to work

That failing, try ::testMod::run_input2 

That failing, try testMod_MP_run_input2

Jim Dempsey

 

0 Kudos
FortranFan
Honored Contributor III
1,207 Views

jimdempseyatthecove wrote:

testMod::run_input2       is supposed to work

That failing, try ::testMod::run_input2 

That failing, try testMod_MP_run_input2

Jim Dempsey

 

Jim,

Note this is not a referencing issue in the debugger.  The debugger does indeed show an entity RUN_INPUT2 under Locals and know there is a component named TEST within it, and that TEST has 2 subcomponents of DAT1 and DAT2.  It's just that the debugger shows DAT1 and DAT2 as having "Undefined Address".  As Steve, it is a problem that the debugger team for Intel Fortran integration with Visual Studio will need to fix.  

0 Kudos
mecej4
Honored Contributor III
1,207 Views

I think that part of the problem for the debugger is that subroutine "toBeCalled" presently takes an assumed size argument. That means that the subroutine receives only the base address of the array, unless some checking options are used in addition to /Zi.

By changing the subroutines in #1 to contained subroutines and by additionaly changing the argument of the subroutine to "real*8, dimension(:) ::dat", I found that with IFort 15.0.3 and VS2013 I was able to inspect the values of the elements of run_input2%test%dat1 in the Locals window.

0 Kudos
shakeham
Beginner
1,207 Views

mecej4 wrote:

I think that part of the problem for the debugger is that subroutine "toBeCalled" presently takes an assumed size argument. That means that the subroutine receives only the base address of the array, unless some checking options are used in addition to /Zi.

By changing the subroutines in #1 to contained subroutines and by additionaly changing the argument of the subroutine to "real*8, dimension(:) ::dat", I found that with IFort 15.0.4 and VS2013 I was able to inspect the values of the elements of run_input2%test%dat1 in the Locals window.

Just tried your solution. It still doesn't work. Problem is the issue occurred even before toBeCalled is invoked.


          run_input2%test%dat1 =>  x  ! issue 1: we cannot examine run_input2%test%dat1 values in visual studio. 

just after this statement. run_input2 has all but undefined address in it.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,207 Views

shakeham,

When all else fails (for me), I insert something like this between the declaration section and the code section:

!DIR$ IF DEFINED(_DEBUG)
real, pointer ::pdat1
... (pointer declarations to other things you have problems with
pdat1 =>  run_input2%test%dat1
p... => ...
...
!DIR$ ENDIF

Depending on what you point at, this may require TARGET on object(s) being pointed to.

Yes, this is a pain, and you should not have to do this. But this may be easier to incorporate into old code than the alternatives.

Jim Dempsey

0 Kudos
Reply