Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
75 Views

Is it possible to add a new member to allocatable array without curropting the pointers to existing members?

Jump to solution

I use this subroutine to add a new segment object to array of segments (sarArray):

      subroutine segArrayAddNewMember(sarArray, segNewMember)
          use class_segment
          implicit none
          type(segment), dimension(:), allocatable, &
                   intent(inout)  :: sarArray
          type(segment), intent(in)     :: segNewMember
          type(segment), dimension(:), allocatable :: sarTemp
          integer intSize
          
          if (allocated(sarArray)) then 
              intSize = size(sarArray)
              allocate(sarTemp(intSize+1))
              sarTemp(1:intSize) = sarArray
              sarTemp(intSize+1) = segNewMember
              deallocate(sarArray)
              call move_alloc(sarTemp, sarArray)
          else 
              allocate(sarArray(1))
              sarArray(1) = segNewMember
          end if
      end subroutine segArrayAddNewMember

However the problem is all of the pointers to existing members become corrupted and the only thing I can think of is the deallocate/moveallocate is causing it.

Is it possible to prevent corruption of pointers?

0 Kudos

Accepted Solutions
Highlighted
New Contributor I
75 Views

I'm not sure what the standard says, but I would definitely not count on pointers to sarArray elements being safe after it has been deallocated and reallocated. The only way to fix this is to make sarArray a linked list rather than an allocatable array. Then you can add/remove elements without changing the existing ones. If you want to keep the allocatable array, you'd have to include a mechanism for reassociating the pointers to the new elements after it is resized, if that is possible in your case.

View solution in original post

0 Kudos
8 Replies
Highlighted
New Contributor I
76 Views

I'm not sure what the standard says, but I would definitely not count on pointers to sarArray elements being safe after it has been deallocated and reallocated. The only way to fix this is to make sarArray a linked list rather than an allocatable array. Then you can add/remove elements without changing the existing ones. If you want to keep the allocatable array, you'd have to include a mechanism for reassociating the pointers to the new elements after it is resized, if that is possible in your case.

View solution in original post

0 Kudos
Highlighted
Black Belt Retired Employee
75 Views

Once you deallocate the array, any pointers to the array or its elements become undefined. Indeed it is certain, given the code above, that the new array will be at different locations than the old array.

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
New Contributor II
75 Views
It can be done by using a container type with allocatable scalar component for your object. Continue using move_alloc for the temporary array but instead of assigning items, use move_alloc for those too.
0 Kudos
Highlighted
New Contributor II
75 Views

Would giving sarArray the TARGET attribute help, or would that at least indicate an error?

0 Kudos
Highlighted
Valued Contributor III
75 Views

In addition (maybe irrelevant),  are you sure the doing a reallocate to increase the size by 1 is a great idea?  If the array is growing that could be really slow. Maybe increasing by a fixed proportion e.g +30% might be better and then downsizing to the final size when it has stopped growing if you want to save the memory

0 Kudos
Highlighted
Valued Contributor III
75 Views

S. PMay wrote:

.. Is it possible to prevent corruption of pointers?

@S. PMay,

Note the Fortran standard essentially places all the responsibility on the coder in situations such as the one in your original post.  You may take note of the following:

  1. AVOID components in derived types ('classes') with POINTER attribute; adopt the ALLOCATABLE attribute instead
  2. if avoidance of POINTER components is not feasible, implement DEFINED assignments in all the derived types that control deep vs shallow copy of the components.  Also implement FINAL procedure bindings ('finalizers') with the necessary cleanup steps for the components with the POINTER attribute.
  3. If you still notice issues after following the suggestions in point #2, create fully reproducible examples and submit support requests at the Intel OSC: https://supporttickets.intel.com/?lang=en-US 

By the way, note the DEALLOCATE statement on line 15 in the code in the original post is superfluous; MOVE_ALLOC on the following line is all you need.

Separately you may want to review this thread in detail: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/701985

 

0 Kudos
Highlighted
Black Belt Retired Employee
75 Views

John Campbell wrote:

Would giving sarArray the TARGET attribute help, or would that at least indicate an error?

No, this would not have any useful effect.

--
Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
Beginner
75 Views

andrew_4619 wrote:

In addition (maybe irrelevant),  are you sure the doing a reallocate to increase the size by 1 is a great idea?  If the array is growing that could be really slow. Maybe increasing by a fixed proportion e.g +30% might be better and then downsizing to the final size when it has stopped growing if you want to save the memory

Thanks for the tip, performance is not an issue here. This routine is only run until input file is over.

FortranFan wrote:

Note the Fortran standard essentially places all the responsibility on the coder [...]

  1. AVOID components in derived types ('classes') with POINTER attribute; adopt the ALLOCATABLE attribute instead
  2. if [...] not feasible, implement DEFINED assignments[...].  Also implement FINAL [...] with the necessary cleanup steps [...]
  3. If you still notice issues[...],submit support requests at the Intel OSC[...]

By the way, note the DEALLOCATE statement on line 15 in the code in the original post is superfluous; [...]

Separately you may want to review this thread in detail: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-fo...

Thanks for very useful comments. all I want is same instance of objects:

segment objects create elements, one segment can belong to two elements. what happens to one segment should affect both elements.

using pointers was my solution. so each element have segment pointer that points to the corresponding segment object in segments array (sarSegments).

Using pointers is the only solution I can think of. In most other OOP languages the class objects are automatically same instance I think.

0 Kudos