- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Forum,
I'm having trouble figuring out how to properly allocate my defined type in a subroutine and return the data to the main program using a structure pointer passed to the subroutine. I suspect I am making an easy mistake but I can't find the right way to set this up and help would be greatly appreciated.
compiled, version 18.0.1.156 Build 20171018:
ifort datTest.f90
On execute I get: "forrtl: severe (157): Program Exception - access violation" as soon as I try to access structure.
Test code, datTest.f90, below.
Thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@keller, scott,
Note the two allocated objects in your two subroutines, getDataPtr and getDataObject, are "local" to those procedures and when the execution returns from those subprograms, those objects can get destroyed. If you intended for your "mydata" objects to be "global: objects instead with "saved" status, you may consider explicit instructions for the same by placing them in your MODULE itself i.e., before the CONTAINS section:
module Test
   implicit none
   type myArrObj
      real , allocatable, dimension(:) :: dat
   end type myArrObj
   ! Declare "global" objects that are saved
   real, allocatable, target, save :: mydata1(:)
   type(myArrObj), target, save :: mydata2
contains
   subroutine getDataPtr(dPtr)
      real, pointer , dimension(:) , intent(out)::dPtr
      allocate(mydata1(10))
      mydata1 = 7.0
      dPtr => mydata1
      return
   end subroutine getDataPtr
   subroutine getDataObject(dPtr)
      type(myArrObj), pointer, intent(out)::dPtr
      allocate(mydata2%dat(10))
      mydata2%dat = 5.0
      dPtr => mydata2
      print *, dPtr%dat ! Allocation happend and data is here
      return
   end subroutine getDataObject
end module Test
program datTest
   use Test
   type(myArrObj), pointer :: ObjPtr => null()
   real, pointer, dimension(:) :: ArrayPtr => null()
   call getDataPtr(ArrayPtr)
   print *, ArrayPtr ! Allocation done in subroutine and data returns w pointer
   call getDataObject(ObjPtr)
   print *, ObjPtr%dat ! forrtl: severe (157): Program Exception - access violation
end program datTest
Separately, you may want to consider moving away from POINTER attribute and work with ALLOCATABLE attribute in Fortran and move away from "globally" saved objects and rather have data in objects allocated in the calling code and given your use of OO-like getter procedures, perhaps you may want to look into OO features in Fortran and employ them instead. The references in this Dr Fortran blog can be helpful for details: https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@keller, scott,
Note the two allocated objects in your two subroutines, getDataPtr and getDataObject, are "local" to those procedures and when the execution returns from those subprograms, those objects can get destroyed. If you intended for your "mydata" objects to be "global: objects instead with "saved" status, you may consider explicit instructions for the same by placing them in your MODULE itself i.e., before the CONTAINS section:
module Test
   implicit none
   type myArrObj
      real , allocatable, dimension(:) :: dat
   end type myArrObj
   ! Declare "global" objects that are saved
   real, allocatable, target, save :: mydata1(:)
   type(myArrObj), target, save :: mydata2
contains
   subroutine getDataPtr(dPtr)
      real, pointer , dimension(:) , intent(out)::dPtr
      allocate(mydata1(10))
      mydata1 = 7.0
      dPtr => mydata1
      return
   end subroutine getDataPtr
   subroutine getDataObject(dPtr)
      type(myArrObj), pointer, intent(out)::dPtr
      allocate(mydata2%dat(10))
      mydata2%dat = 5.0
      dPtr => mydata2
      print *, dPtr%dat ! Allocation happend and data is here
      return
   end subroutine getDataObject
end module Test
program datTest
   use Test
   type(myArrObj), pointer :: ObjPtr => null()
   real, pointer, dimension(:) :: ArrayPtr => null()
   call getDataPtr(ArrayPtr)
   print *, ArrayPtr ! Allocation done in subroutine and data returns w pointer
   call getDataObject(ObjPtr)
   print *, ObjPtr%dat ! forrtl: severe (157): Program Exception - access violation
end program datTest
Separately, you may want to consider moving away from POINTER attribute and work with ALLOCATABLE attribute in Fortran and move away from "globally" saved objects and rather have data in objects allocated in the calling code and given your use of OO-like getter procedures, perhaps you may want to look into OO features in Fortran and employ them instead. The references in this Dr Fortran blog can be helpful for details: https://software.intel.com/en-us/blogs/2013/12/30/doctor-fortran-in-its-a-modern-fortran-world
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@FortranFan: Thanks so much for your post, it helped me understand the deallocate behavior in the subroutine better and your comments pointed me in the direction I was looking for. It was even easier to do what I was hoping. I'm attaching the modified version in case anyone else is interested in the same issue.
 
					
				
				
			
		
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page