Hi all,
I’m having some trouble with some fortran code segfaulting when optimization is enabled in pgfortran.
Specifically, I’ve set up a 3D allocatable array. Under some circumstances, its allocated, and under these same circumstances, it is read later in the code. The circumstances which would prevent it from being allocated also prevent it from being accessed later in the code. However, when I compile with optimization (-O2) enabled, I am seeing segfaults resulting from accessing memory address 0x0. If I allocate this array even if the code shouldn’t access it, the program runs to completion. The problem also goes away if I compile with bounds checking (-Mbounds) enabled. In addition, the code compiles and runs without issue with gfortran, even when -O2 is used.
Below is a representative simplification. I’ve tried to make it as simple as possible. Note that in the actual code, I’m not doing things like empty ‘else’ statements. There is meaningful code within those regions. I removed as much code as I could while still making the problem repeatable.
It seems as though the compiler is attempting to perform the operations inside the conditionals even if the criteria is not met. Presumably this would be an optimization technique, and the results would only be used if the conditions were met?
I appreciate any help with this.
-Scot
module testmod
real utest
real, allocatable :: height(:,:),heightveg(:,:),can(:,:,:), z(:), zm(:)
integer, allocatable :: cell(:,:,:)
integer mx, my, mz, ktest,un, ustar1, ustar2, el
integer i,j,k,kk,klow, dummy
end module
program main
use testmod
implicit none
ktest = 0
mx = 10
my = 10
mz = 10
utest = 0.0
un = 0
ustar2 = 0
dummy = 0
allocate(height(mx,my), heightveg(mx,my))
allocate(cell(mx,my,mz),zm(mz), z(mz))
!allocate(can(mx,my,mz))
height(:,:) = 0.0
heightveg(:,:) = 0.0
cell(:,:,:) = 0
zm(:) = 0.0
z(:) = 0.0
j=1
i=1
!this whole loop should do nothing. all the conditions for the 3 if blocks below should
!not be met.
do k=2,mz
!even though this if block should never be executed (cell is always = 0), removing it allows the code to run
if(cell(i,j,k) .ge. 1)then
if(height(i,j) .gt. 0 .and. cell(i,j,k) .ne. 3)then
else
endif
endif
!because heightveg is zero everywhere, nothing inside this if statement should be
!executed. Even so, allocating the array 'can', which is only used within this if
!statement, allows the program to run to completion
if(heightveg(i,j) .ge. 1)then
if(k .le. 5)then
else
if(can(i,j,ktest) .ne. 0.0)then
el=utest
endif
endif
endif
if(zm(k) .ge. 1)then
do kk=2,mz
klow=kk
if(max(height(i,j),heightveg(i,j))<z(kk))exit !replacing 'exit' with 'dummy = dummy + 1' allows the program to run to completion
enddo
if(k .eq. klow+1)then
if(height(i,j) .ge. heightveg(i,j))then
else
dummy = dummy + 1
endif
endif
if(k .gt. klow)then
if(heightveg(i,j) .gt. height(i,j))then
if(un .ge. 0)then
else
endif
else !commenting this line out results in a working executable
endif
endif
endif
enddo
print *, dummy
end program