Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29287 Discussions

passing pointer to a subroutine fails

Ekaterina_M_
Beginner
816 Views

Dear all, 

I am facing an issue with passing a pointer to a subroutine. Here is a simplified version of my code:

      program test_ptr

      interface
      subroutine sub(iptr)
      dimension iptr(5)
      end subroutine sub
      end interface

      save

      integer, dimension(:), pointer :: iptr

      allocate(iptr(5))
      iptr = 0

      call sub(iptr)

      deallocate(iptr)

      end


      subroutine sub(iptr)

      integer, dimension(:), pointer :: iptr
c      dimension iptr(5)

      end

If I declare iptr allocatable in the subroutine (commented line), everything goes fine. However I want iptr be a pointer in the subroutine, and in this case my code fails on a memory fault at the moment it enters the subroutine.

The attached code does not fail (must be too simple for that) but valgrind complains about invalid reads.

I have compiled with gfortran and passed through valgrind the same code, and there were no issues at all (except that gfortran insisted I add an interface block).

My compile/run instructions and output follow:

> ifort -g -O0 test_pointer.F; valgrind --leak-check=full --show-reachable=yes ./a.out
==18156== Memcheck, a memory error detector
==18156== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==18156== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==18156== Command: ./a.out
==18156==
==18156== Invalid read of size 8
==18156==    at 0x403256: sub_ (test_pointer.F:23)
==18156==    by 0x403095: MAIN__ (test_pointer.F:16)
==18156==    by 0x402E7D: main (in /home/emakarov/FlowSimulator/test_pointer/a.out)
==18156==  Address 0x5c1f120 is not stack'd, malloc'd or (recently) free'd
==18156==
==18156== Invalid read of size 8
==18156==    at 0x403259: sub_ (test_pointer.F:23)
==18156==    by 0x403095: MAIN__ (test_pointer.F:16)
==18156==    by 0x402E7D: main (in /home/emakarov/FlowSimulator/test_pointer/a.out)
==18156==  Address 0x5c1f130 is not stack'd, malloc'd or (recently) free'd
==18156==
==18156==
==18156== HEAP SUMMARY:
==18156==     in use at exit: 32 bytes in 1 blocks
==18156==   total heap usage: 3 allocs, 2 frees, 68 bytes allocated
==18156==
==18156== 32 bytes in 1 blocks are still reachable in loss record 1 of 1
==18156==    at 0x4C26E77: calloc (vg_replace_malloc.c:593)
==18156==    by 0x5A1C53F: _dlerror_run (in /lib64/libdl-2.11.2.so)
==18156==    by 0x5A1C0A9: dlsym (in /lib64/libdl-2.11.2.so)
==18156==    by 0x40D90E: for__aio_init (in /home/emakarov/FlowSimulator/test_pointer/a.out)
==18156==    by 0x405C29: for_rtl_init_ (in /home/emakarov/FlowSimulator/test_pointer/a.out)
==18156==    by 0x402E78: main (in /home/emakarov/FlowSimulator/test_pointer/a.out)
==18156==
==18156== LEAK SUMMARY:
==18156==    definitely lost: 0 bytes in 0 blocks
==18156==    indirectly lost: 0 bytes in 0 blocks
==18156==      possibly lost: 0 bytes in 0 blocks
==18156==    still reachable: 32 bytes in 1 blocks
==18156==         suppressed: 0 bytes in 0 blocks
==18156==
==18156== For counts of detected and suppressed errors, rerun with: -v
==18156== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)

 

> gfortran -g -O0 test_pointer.F; valgrind --leak-check=full --show-reachable=yes ./a.out
==18171== Memcheck, a memory error detector
==18171== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==18171== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==18171== Command: ./a.out
==18171==
==18171==
==18171== HEAP SUMMARY:
==18171==     in use at exit: 0 bytes in 0 blocks
==18171==   total heap usage: 22 allocs, 22 frees, 12,091 bytes allocated
==18171==
==18171== All heap blocks were freed -- no leaks are possible
==18171==
==18171== For counts of detected and suppressed errors, rerun with: -v
==18171== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

I would appreciate any help with this issue.

Ekaterina.

 

0 Kudos
4 Replies
mecej4
Honored Contributor III
816 Views

The subroutine you have is of such a nature that the Fortran standards require you to provide an explicit interface to it in subprograms that contain a call to the subroutine. You provided an interface with an interface block, but the interface block does not match the declaration of the function. In effect, you deceived the compiler. If you recompile with the option "-warn interfaces", the compiler will tell you about the incorrect interface.

You mention "attached code", but I see no attachments. If you change Line-5 of the code insert to match Line-25, the code compiles and runs fine.

0 Kudos
Ekaterina_M_
Beginner
816 Views

Thanks a lot mecej4!

The "attached code" was in fact the one I cited. 

You are totally right about the interface mismatch, I have tried so many different combinations (in the beginning, I had interface block at all) that I went to this error and I didn't notice it.

The problem is resolved now.

 

0 Kudos
FortranFan
Honored Contributor III
816 Views

Ekaterina M. wrote:

Thanks a lot mecej4!

The "attached code" was in fact the one I cited. 

You are totally right about the interface mismatch, I have tried so many different combinations (in the beginning, I had interface block at all) that I went to this error and I didn't notice it.

The problem is resolved now.

You may want to look into using modules and submodules (a Fortran 2008 feature recently introduced in Intel Fortran 16.0 beta version) and the benefits they bring, especially with providing explicit interfaces and structuring code - see Dr Fortran blog.  Can you replace your external procedures with module procedures as shown below with your example?  

module m

   implicit none

   private

   public :: sub

contains

   subroutine sub(iptr)

      integer, dimension(:), pointer :: iptr
      !      dimension iptr(5)

   end

end module m
program test_ptr

   use m, only : sub

   save

   integer, dimension(:), pointer :: iptr

   allocate(iptr(5))
   iptr = 0

   call sub(iptr)

   deallocate(iptr)

end

 

0 Kudos
Ekaterina_M_
Beginner
816 Views

Thank you, FortranFan!

0 Kudos
Reply