I'm running into a issue within a code that works fine in 2017 but crashes in 2018.
program Console1 implicit none type tO integer :: aNumber real, allocatable, dimension(:) :: arr end type type (tO), allocatable, dimension(:) :: arTOs type (tO) :: oTo integer i,j,m m=3 allocate(arTOs(m)) do i=1,size(arTOs) write(*,'(a,i1)') 'allocating, loop:',i oTo=arTOs(i) oTo%aNumber=i+m if (allocated(oTo%arr)) then write(*,'(a)') 'oTo%arr IS already allocated' endif allocate(oTo%arr(oTo%aNumber)) do j=1,size(oTo%arr) oTo%arr(j)=real(i+j) enddo arTOs(i)=oTo enddo CONTINUE end program Console1
When I run this code with the 126.96.36.199 Compiler, the first loop works as expected, but in the second loop Exception:
forrtl: severe (151): allocatable array is already allocated was thrown.
And the interesting past is that the line above 'allocated(oTo%arr)' is still false.
And, as mentioned above, this code works fine with 188.8.131.52.
Any Hints what I am doing wrong here?
I think line
17 16 is the issue. I'm not sure if this is standard conforming. If this is not standard conforming, the compiler reaction is unpredictable. For i=2 oTo is set to arTOs(2), which has a not allocated component arr. I don't know if reallocation of left hand side (default since PSXE 2017) can deallocate type sub-components oTo%arr? If this is conforming to standard, PSXE2018 seems to be wrong here, because is this case oTo%arr is always not allocated after line 17 16.
Why don't you work directly with arTOs?
Best regards, Johannes
ps: running the PSXE 2018 exe with PSXE 2017 runtime libs, no error occurs (changing the setting in VS tools->options->...), dynamic linked.
Thx for your response.
I guess you localized the issue in line 16 ('oTo=arTOs(i)') and not line 17,
however, the construct: 'oTo=arTOs(i); oTo%...', and not 'arTOs(i)%...' is used several times in our production code, so changing the code is not my preferred opinion.
And the question is still why does this code run in versions prior 18.x?
I believe that the problem is actually with Line-16. The LHS is a user-defined-type, as is the expression on the RHS. Neither of the components of the RHS expression (of derived type) have been defined. Therefore, the behavior of the assignment statement is "undefined".
If you look a little deeper, you can see that there may be major hidden problems in your production code if this pattern of coding is used. The copying of a derived type variable can get complicated when there are one or more allocatable components. Copying the first component in your example is not a problem -- it is just a scalar integer. The second component is an allocatable array, so things are a bit more complicated if reallocate-on-assignment is being done.
Whether the compiler can (when asked, with suitable options) detect the error (at compile or run time) is a quality-of-implementation question.
Had you used pointer variables, the story would have been quite different.
Furthermore, even if the compiler can detect usage of undefined variables, you are likely to see many nuisance reports errors if you ask it to do so.
>> Line-16. The LHS is a user-defined-type, as is the expression on the RHS. Neither of the components of the RHS expression (of derived type) have been defined. Therefore, the behavior of the assignment statement is "undefined".
Isn't the unallocated array descriptor defined? Defined in the sense that it contains not just random junk, but rather is initialized (defined) as being unallocated. Yea, I know Fortran-speak has "defined" meaning variable=somethingAlreadyDefined. On the other hand, this can be taken to mean undefined==uninitializedLeftoverJunkData. An unallocated(deallocated) array descriptor is definitely .NOT. uninitializedLeftoverJunkData
I believe the copy of the (component of user defined type being an) unallocated array descriptor should be a valid statement. IMHO this is an error in the runtime code that assumes the array is allocated.
Added: granted, the value of the integer component (aNumber) was undefined, and you get what you get.
allocate(arTOs(m)) allocate(arTOs(1)%arr(2)) ! now allocated arTOs(1)%aNumber = 0 ! now defined arTOs(1)%arr = 0.0 ! now defined deallocate(arTOs(1)%arr) ! now unallocated (but formerly allocated and defined) arr ... oTo=arTOs(1) ! copy with unallocated (but formerly allocated and defined) arr
The above satisfies the "defined" (IMHO), but other than for aNumber being defined, I see no difference between the above code and the original code of this thread.
The program is fine, as far as I can tell. The assignment in line 16 should cause oto%arr to become deallocated because arTOs(2)%arr is not allocated, but the compiler code isn't completely resetting things (perhaps a flag needs to be cleared.) Please submit a report to Intel support.