move_alloc from polymorphic causes segfault

move_alloc from polymorphic causes segfault

Ritratto di Ferdinand T.

Hello again,

in the example program below I experienced a problem with the MOVE_ALLOC intrinsic, where the 'TO' argument is polymorphic, but the 'FROM' is not.

I am aware that there have been recent compiler issues with MOVE_ALLOC, nevertheless I would be happy to get some helpful advice again whether it's the compiler or me who is wrong in this case.

module m
    ! a derived type
    type other_type
        integer :: i = 5
    end type
  
    ! container, has allocatable component of derived type
    type:: container_type
        CLASS(other_type), allocatable :: alloc_comp  ! (*)
    end type
end module
 
  
program p
    use m
    implicit none
    type(container_type) :: original
    type(container_type), allocatable :: copy
    TYPE(other_type), allocatable :: alloc_var        ! (**)
   
    ! initialize alloc. comp. in 'original' container
    allocate(alloc_var)
    call move_alloc(alloc_var,original%alloc_comp)
   
    ! copy the container
    allocate(copy, source=original)
  
    ! check if ultimate allocatable components have been copied, too
    print *, allocated(copy%alloc_comp)  ! answer: T
  
    ! read ultimate alloc. components from copy
    print *, copy%alloc_comp%i           ! CRASH (access violation)
 
end program

The list below shows the compilation status for variuous combination of polymoprhic/non-polymoprhic FROM and TO arguments in MOVE_ALLOC.

line (*)    line (**)      compilation?
[TO]        [FROM]
class       class          OK
type        type           OK
class       type           CRASH: access violation, as described in example code
type        class          CRASH: compiler seg. violation (but illegal fortran code)

While the last configuration is illegal (polymorphic 'FROM' needs polymorphic 'TO'), I think the previous should be legal (if not, I whish the compiler could raise an error, because the source of that error was hard to find in my original code).

Remarks:

  • After executing MOVE_ALLOC, the polymorphic 'TO' component seems to be allocated with the correct dynamic type of 'FROM' and can also be read (within an additional select type).
  • However, the so initialized component of the container is not correctly copied via ALLOCATE from the SOURCE expression.
    While the allocation status in the copy is 'allocated', accessing the component causes a segmentation fault.
  • The use of ALLOCATE(original%alloc_comp, SOURCE=alloc_var) instead of MOVE_ALLOC for the initialization fixes the problems.

Best regards and thanks for your answers,

Ferdinand

5 post / 0 new
Ultimo contenuto
Per informazioni complete sulle ottimizzazioni del compilatore, consultare l'Avviso sull'ottimizzazione
Ritratto di Ferdinand T.

While doing more research on this, I found an old thread concerning the same issue in ifort 12 here:

http://software.intel.com/en-us/forums/topic/281144

Is this issue still present in version 13.x?

Nevertheless, the proposed workaround there ('make both arguments polymorphic') doesn't help me in my original code (/= the example), where the 'TO' argument is an abstract class. Declaring both arguments as 'class', they still cause the segmentation fault after beeing copied via ALLOCATE (nevertheless both polymorphic). Maybe I can post more details from my original code, if those can be helpful in fixing this problem.

Ritratto di Steve Lionel (Intel)

The internal compiler error is already fixed for a release later this year.

The problem from the thread you linked is not present in 13.x. Yours is a new issue that I have escalated as DPD200241859. I will let you know of any progress. What I see is that the ALLOCATED call is returning incorrect information - my guess is that the MOVE_ALLOC, where the destination is polymorphic but the source is not, is not properly filling in the destination's descriptor.

Steve
Ritratto di Ferdinand T.

Thanks for the clarification. The ALLOCATED call indeed returns TRUE, but I think this is more or less correct in the way that the ultimate allocatable component should be allocated after creating a copy with ALLOCATE*. The problem is that, in fact, it is not. I also got the impression that the MOVE_ALLOC messed it up.

Regards, Ferdinand

*) This is what I concluded from the Intel® Fortran Compiler XE 13.1 reference pages - which I find very helpful and well written also for less experienced users (while the standard or other manuals are a lot harder to read without prior knowledge of all the finer fortran details). Just had to mention that ;-).

http://software.intel.com/sites/products/documentation/doclib/stdxe/2013... (second paragraph from the end)

Ritratto di Steve Lionel (Intel)

The newer issue is now also fixed for a release later this year.

Steve

Accedere per lasciare un commento.