关于fortran的分段错误

问题遇到的现象和发生背景

出现了分段错误,一直找不到错误原因,错误格式如下。

img

数据格式如下(一部分)

img


数据为:文件编号(24835),纬度(60.015),经度(101.802),高度(5640),雷达反射率(-33.884),C1mask(0),C4type(0),温度(235.9),陆地-大气判断系数(0)

在对这些数据进行处理的时候首先编写了如下的fortran程序:

program sample
  implicit none


!-9=missing / 0=clear / 1=warm water / 2=supercooled water /
! 3=3d ice / 4=2d plate / 5=mixture of 3d ice and 2d plate /
! 6=liquid drizzle / 7=mixed-phase drizzle / 8=rain / 9=snow /
! 10=water+liquid driz / 11=water+rain / 12=mixed-phase /13=unknown )

 
  integer::i,k,nx,n=40000000,nalt=83
  real::la,lo,lonmin,lonmax,latmax,latmin,count_record
  real::ice,snow,clear,warm_water,supercooled_water,twod_plate,mixture,Mixed_phase_drizzle,rain
  real::ice_per,snow_per,clear_per,warm_water_per,supercooled_water_per,twod_plate_per,mixture_per
  real::Mixed_phase_drizzle_per,rain_per
 integer,dimension(:),allocatable::profile_number
 real,dimension(:),allocatable::lon,lat
 real,dimension(:,:),allocatable::ref,c1mask,alt,c4type,d_n,temp
 
 allocate(profile_number(1:n))
 allocate(lat(1:n))
 allocate(lon(1:n))
 allocate(ref(1:n,1:nalt))
 allocate(alt(1:n,1:nalt))
 allocate(c4type(1:n,1:nalt))
 allocate(c1mask(1:n,1:nalt))
 allocate(d_n(1:n,1:nalt))
 allocate(temp(1:n,1:nalt))


 write(*,*) 'allocated'
 
 open(unit=65,file='arctic_cmask_type_2007.txt',status='old')
 write(*,*)"already open"
 
 i=0
 do
    i=i+1
    do k=nalt,1,-1
    read(65,*,end=1000)profile_number(i),lat(i),lon(i),alt(i,k),ref(i,k),c1mask(i,k),c4type(i,k),temp(i,k),d_n(i,k)
    end do
  write(*,*)i
  end do
1000 close(65)
  nx=i-1
  write(*,*)nx


  write(*,*)"already"
  !--------------------------------------------
  
  open(unit=66,file='per1.txt',status='replace')
  open(unit=67,file='per2.txt',status='replace')
  open(unit=68,file='per3.txt',status='replace')
  
latmin=-90
latmax=-88
count_record=0

do la=-90,90,2
          write(*,*)la
         lonmin=-180
         lonmax=-178

         do lo=-180,180,2
            do i=1,nx,1
                  if(latmin<=lat(i).and.latmax>lat(i))then
                     if(lonmin<=lon(i).and.lonmax>lon(i))then
                        count_record=count_record+1
                       
!---------------------------------------------------------------------------

                      do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if (c4type(i,k)==3)then
                             ice=ice+1
                          end if
                          exit
                          end if
                       end do

                       do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if(c4type(i,k)==9)then
                             snow=snow+1
                          end if
                          exit
                          end if
                       end do

                       do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if(c4type(i,k)==0)then
                             clear=clear+1
                             end if
                           exit
                          end if
                       end do

                       do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if(c4type(i,k)==1)then
                             warm_water=warm_water+1
                             end if
                           exit
                          end if
                       end do

                       do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if(c4type(i,k)==2)then
                             supercooled_water=supercooled_water+1
                             end if
                           exit
                          end if
                       end do

                        do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if(c4type(i,k)==4)then
                            twod_plate=twod_plate+1
                             end if
                           exit
                          end if
                       end do

                        do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if(c4type(i,k)==5)then
                             mixture=mixture+1
                             end if
                           exit
                          end if
                       end do

                        do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if(c4type(i,k)==7)then
                            Mixed_phase_drizzle=Mixed_phase_drizzle+1
                             end if
                           exit
                          end if
                       end do

                       do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if(c4type(i,k)==8)then
                             rain=rain+1
                             end if
                           exit
                          end if
                       end do
                       
     
                     end if
                  end if
               end do
            
               ice_per=100*ice/count_record
               snow_per=100*snow/count_record
               clear_per=100*clear/count_record
               warm_water_per=100*warm_water/count_record
               supercooled_water_per=100*supercooled_water/count_record
               twod_plate_per=100*twod_plate/count_record
               mixture_per=100*mixture/count_record
               Mixed_phase_drizzle_per=100*Mixed_phase_drizzle/count_record
               rain_per=100*rain/count_record

               
            if(count_record>0)then
             write(66,'(2F10.1,3F10.3)')la-90,lo-180,ice_per,snow_per,rain_per
             write(67,'(2F10.1,3F10.3)')la-90,lo-180,clear_per,warm_water_per,supercooled_water_per
             write(68,'(2F10.1,3F10.3)')la-90,lo-180,twod_plate_per,mixture_per,Mixed_phase_drizzle_per
             
            end if
                    
            count_record=0
            
            snow=0
            ice=0
            clear=0
            warm_water=0
            supercooled_water=0
            twod_plate=0
            mixture=0
            Mixed_phase_drizzle=0
            rain=0
           
            lonmin=lonmin+2
            lonmax=lonmax+2

         end do

         latmin=latmin+2
         latmax=latmax+2

      end do
      
      stop
      end program sample

能正常运行。

但是现在执行如下程序 主框架没有变只是变了一个判断条件就会出现上边所示的分段错误。

program sample
  implicit none


!-9=missing / 0=clear / 1=warm water / 2=supercooled water /
! 3=3d ice / 4=2d plate / 5=mixture of 3d ice and 2d plate /
! 6=liquid drizzle / 7=mixed-phase drizzle / 8=rain / 9=snow /
! 10=water+liquid driz / 11=water+rain / 12=mixed-phase /13=unknown )

 
  integer::i,k,j,nx,n=30000000,nalt=83
  real::la,lo,lonmin,lonmax,latmax,latmin,count_record
  real::precipitation,precipitation_per,snowfall_real,snowfall_real_per
 integer,dimension(:),allocatable::profile_number
 real,dimension(:),allocatable::lon,lat
 real,dimension(:,:),allocatable::ref,c1mask,alt,c4type,d_n,temp
 
 allocate(profile_number(1:n))
 allocate(lat(1:n))
 allocate(lon(1:n))
 allocate(ref(1:n,1:nalt))
 allocate(alt(1:n,1:nalt))
 allocate(c4type(1:n,1:nalt))
 allocate(c1mask(1:n,1:nalt))
 allocate(d_n(1:n,1:nalt))
 allocate(temp(1:n,1:nalt))


 write(*,*) 'allocated'
 
 open(unit=65,file='arctic_cmask_type_2007DJF.txt',status='old')
 write(*,*)"already open"
 
 i=0
 do
    i=i+1
    do k=nalt,1,-1
    read(65,*,end=1000)profile_number(i),lat(i),lon(i),alt(i,k),ref(i,k),c1mask(i,k),c4type(i,k),temp(i,k),d_n(i,k)
    end do
  write(*,*)i
  end do
1000 close(65)
  nx=i-1
  write(*,*)nx


  write(*,*)"already"
  !--------------------------------------------
  
  open(unit=66,file='snowfall_per.txt',status='replace')
  open(unit=67,file='gound_snowfall_per.txt',status='replace')
  open(unit=68,file='precipitation_per.txt',status='replace')
  
latmin=-90
latmax=-88
count_record=0

do la=-90,90,2
          write(*,*)la
         lonmin=-180
         lonmax=-178

         do lo=-180,180,2
            do i=1,nx,1
                  if(latmin<=lat(i).and.latmax>lat(i))then
                     if(lonmin<=lon(i).and.lonmax>lon(i))then
                        count_record=count_record+1
                                                 
!---------------------------------------------------------------------------                       
                        do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                            if(ref(i,k)>-10)then
                              precipitation=precipitation+1 
                           end if
                           exit
                             end if                  
                          end do


                          do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                            if(ref(i,k)>-10.and.temp(i,k)<275.15)then
                              snowfall_real=snowfall_real+1 
                           end if
                           exit
                             end if                  
                          end do

                          
                      
                     end if
                  end if
               end do

              precipitation_per=precipitation*100/count_record
              snowfall_real_per=snowfall_real*100/count_record
         
               if(count_record>100)then
             write(68,'(2F10.1,2F10.3)')la-90,lo-180, precipitation_per,snowfall_real_per
            end if
                    
            count_record=0
       
            snowfall_real=0
            precipitation=0
            lonmin=lonmin+2
            lonmax=lonmax+2

         end do

         latmin=latmin+2
         latmax=latmax+2

      end do
      
      stop
      end program sample

两段代码根本区别就是
第一个代码:


                       do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                             if (c4type(i,k)==3)then
                             ice=ice+1
                          end if
                          exit
                          end if
                       end do  

而第二个代码:


                         do k=1,nalt,1
                          if(d_n(i,k)==0.and.d_n(i,k-1)==3)then
                            if(ref(i,k)>-10.and.temp(i,k)<275.15)then
                              snowfall_real=snowfall_real+1 
                           end if
                           exit
                             end if                  
                          end do

不知为什么加一个判断条件就会出现分段错误,并且不知道怎么改。
有没有可以帮忙解决一下这个问题,经常会碰到这类问题只能一点一点试,有的时候会正常,但不知道为什么。

do 循环不能使用负数值,程序编译会报错。比如:

img


想产生 n 为-180,180,2 的序列,可以使用n 为 0,360,2 ,循环体内 n-180.

img

段错误需要调试,不仅要代码,还要输入文件。
你这个肯定会数组越界

img

如果 .and. 之前的那个条件不满足,后面的这个可能不会参与计算,也就不报错。