Deallocation fails - Hard to explain case ( if + class )

Deallocation fails - Hard to explain case ( if + class )

Dear All,

I have noticed the following strange behaviour. In the following example, I define a class component of a type, named alpha_set, and this type is a component of another type, beta_set. I also define two arrays of type beta_set. The command in the main program:

    if (allocated(bset2)) deallocate(bset1) 

or the class declaration of alpha_set:

    class(alpha), dimension(:), allocatable :: member
   
causes the final deallocation statement to fail with error 153 (allocatable array or component is not allocated - version  13.1.0.146). 

I am not sure if this is an expected behaviour. Please let me know what you think. Many thanks.

Here is the code: 

 module mini_type
implicit none
type alpha
 real :: hi
end type alpha
type alpha_set
 class(alpha), dimension(:), allocatable :: member ! <- if class changes to type, runs properly
end type alpha_set
type beta_set
 type(alpha_set), dimension(:), allocatable :: member
end type beta_set
type(beta_set), dimension(:), allocatable, target :: bset1, bset2 
end module mini_type
program test_mini
use mini_type
 integer :: i
 allocate(bset1(10))
 if (allocated(bset2)) deallocate(bset1) ! <-- if commented runs properly
 do i=1,size(bset1),3
 allocate(bset1(i)%member(3))
 end do 
 do i=1,size(bset1)
 if (allocated(bset1(i)%member)) then
 deallocate(bset1(i)%member)
 end if
 end do 
end program test_mini 

 

publicaciones de 10 / 0 nuevos
Último envío
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.

As an experiment, remove ", bset2" from the declaration that creates bset1, change allocated(bset2) to allocated(bset1)

Compile with same options and run.

Your original code should have run without error, but if the test succeeds, then this may be indicative of an error in dead code elimination (code manipulating and producing unused results elimination). This may help the support people in isolating the problem.

Jim Dempsey

www.quickthreadprogramming.com

Hi Jim,

The changes you proposed create the following code that also doesn't run and terminates with the same error as before. I forgot to mention that code fails when it deallocates bset1(i)%member. Could you please explain dead code elimination a bit more for this case ?  Thank you for your suggestion.

Kostas
 

  
module mini_type
implicit none
type alpha
 real :: hi
end type alpha
type alpha_set
 class(alpha), dimension(:), allocatable :: member ! <- if class changes to type, runs properly
end type alpha_set
type beta_set
 type(alpha_set), dimension(:), allocatable :: member
end type beta_set
type(beta_set), dimension(:), allocatable, target :: bset1!, bset2  <-- change 1 : removed bset2 from declaration statement
end module mini_type
program test_mini
use mini_type
 integer :: i
 if (allocated(bset1)) deallocate(bset1) ! <-- change 2 : bset2 is now bset1, also moved the statement before the allocation of bset1
allocate(bset1(10))
 do i=1,size(bset1),3
 allocate(bset1(i)%member(3))
 end do 
 do i=1,size(bset1)
 if (allocated(bset1(i)%member)) then
 deallocate(bset1(i)%member)
 end if
 end do 
end program test_mini 

"Dead code elimination" is an optimization that is not relevant here. I am looking into this further.

Steve - Intel Developer Support

I believe that the compiler is not properly initializing the state of the alpha_set arrays. I have escalated this as issue DPD200241489 and will let you know of any progress.

Steve - Intel Developer Support

Dead code elimination:

When the compiler can determine when a code branch is never taken, thus never be excuited, the compiler removes the code from the object file. This code was called dead code. The compiler writers then saw, that when the results of a computation are not used, then why not remove the code that performs those calculations (call those statement dead code).

In your original code, you had an array that was allocated and never used. Other than for the execution statement of an if test that could be determined as to never being executed (IOW as dead code). Dead code of that IF test and .true. statement never to be execuited, then removed the only reference to an array was allocate. I was making a supposition that the compiler may have removed the allocation as well.

Supposition continues to by removing the allocation that the declaration for that array could also me removed (such that the array descriptor need not be initialized). My supposition (and area for exploration) is the "unused" array descriptor was not cleanly removed and thus an error was exposed. This is all guess work on my part.

Jim Dempsey

www.quickthreadprogramming.com

It is true that removing the reference to bset2 causes bset2 itself to be completely removed from the code. Why this has an effect on the error, I don't yet know. The compiler did not do dead code elimination, as either the code was there (and was executed), or not there in the first place.

Steve - Intel Developer Support

My sincere thanks to both of you for your explanations and feedback!

>>It is true that removing the reference to bset2 causes bset2 itself to be completely removed from the code.

My supposition was that the constructor for the bset2 array descriptor was removed as part of the dead code elimination process, however the uninitialized array descriptor was left around. Then on exit from scope, the auto deallocate of allocatables used the uninitialized array descriptor. That is one theory. The other theory is the token for the bset2 array descriptor was not removed and the compiler confused the token for bset1 with token for bset2 thus referencing an uninitialized array descriptor or referencing a compile time allocated object (C/C++ object allocated for compilation purposes), that was subsiquently deleted/freed.

Jim Dempsey

www.quickthreadprogramming.com

This problem has been fixed for a release later this year.

Steve - Intel Developer Support

Deje un comentario

Por favor inicie sesión para agregar un comentario. ¿No es socio? Únase ya