2014-09-18 111 views
0

我正在使用一箇舊的fortran程序給我打開一個netcdf文件,讀取它的內容,執行一些計算和插值,並將數據寫入另一個文件格式。我在fortran方面的經驗很少,所以請任何幫助將深表謝意。Fortran - nf90_open - SIGSEGV

程序成功編譯:

ifort -c -CB -CU -ftrapuv -par_report0 -vec_report0 -heap-arrays -O0 -stand f90 -check all -traceback -fstack-protector -assume protect_parens -implicitnone -debug -gen-interfaces -check arg_temp_created -ftrapuv -g -convert big_endian -I/opt/cray/netcdf/4.3.0/INTEL/130/include/ CAM_netcdf_to_WRF_intermediate.f90 ; ifort CAM_netcdf_to_WRF_intermediate.o -L/opt/cray/netcdf/4.3.0/INTEL/130/lib -lnetcdf -lnetcdff 

程序崩潰,運行出界,而試圖在netCDF文件閱讀:

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7657d33 in nf_open_ (A1=0x18 <Address 0x18 out of bounds>, A2=0x4e04bc <__NLITPACK_19>, 
    A3=0x7fffffff90ec, C1=128) at fort-control.c:27 
27  fort-control.c: No such file or directory. 

運行GDB,使用 'BT全':

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7657d33 in nf_open_ (A1=0x18 <Address 0x18 out of bounds>, A2=0x4e04bc <__NLITPACK_19>, 
    A3=0x7fffffff90ec, C1=128) at fort-control.c:27 
27  fort-control.c: No such file or directory. 
(gdb) bt full 
#0 0x00007ffff7657d33 in nf_open_ (A1=0x18 <Address 0x18 out of bounds>, 
    A2=0x4e04bc <__NLITPACK_19>, A3=0x7fffffff90ec, C1=128) at fort-control.c:27 
     B1 = 0x0 
     B3 = 5113020 
#1 0x00007ffff76630ac in NETCDF::nf90_open (
    path=<error reading variable: Cannot access memory at address 0x18>, mode=0, ncid=-858993460, 
    chunksize=<error reading variable: Cannot access memory at address 0x0>, 
    cache_size=<error reading variable: Cannot access memory at address 0x0>, 
    cache_nelems=<error reading variable: Cannot access memory at address 0x0>, 
    cache_preemption=<error reading variable: Cannot access memory at address 0x0>, 
    comm=<error reading variable: Cannot access memory at address 0x0>, 
    info=<error reading variable: Cannot access memory at address 0x0>, .tmp.PATH.len_V$ffc=128) 
    at netcdf4_file.f90:64 
     nf90_open = -144388088 
     ret = 0 
     preemption_out = 0 
     nelems_out = -1 
     size_out = 0 
     preemption_in = 32767 
     nelems_in = -134664192 
     size_in = 32767 

該方案是如下:

program CAM_netcdf_to_WRF_intermediate 
    use netcdf 
    implicit none 

    ! Declarations: 
    integer, parameter :: outfile_diagnostics = 16 
    integer, parameter :: infile_CAM_files_and_dates = 15 
    character(len=24) :: HDATE 

    ! dimensions: 
    integer, parameter :: nx_CAM=288,ny_CAM=192,nz_CAM=26 & 
     ,nfields=5,nfields2d=9,nfields2d_to_read=5 & 
     ,nz_soil=4,nz_CLM=1,nfields_soil=2 
    integer, parameter :: nz_WRF=38 
    character(len=128) :: netcdf_cam_filename,netcdf_clm_filename,netcdf_pop_filename 
    character(len=128) :: netcdf_ice_filename 
    integer :: iEOF 
    logical :: EOF 

    ! open outpuf log file: 
    open(outfile_diagnostics,form='formatted',file="Output/CCSM2WRF.log") 

    ! read the first date and netcdf file name from the input file: 
    open(infile_CAM_files_and_dates,form='formatted',file="Input/CCSM2WRF.input") 
    read(infile_CAM_files_and_dates,*,iostat=iEOF) netcdf_cam_filename,netcdf_clm_filename,& 
         netcdf_pop_filename,netcdf_ice_filename,hdate 
    if (iEOF<0) then; 
print *, "EOF True" 
    EOF=.true.; 
    else; 
print *, "EOF False" 
    EOF=.false.; 
    end if 

    call dummy_read(nz_WRF,hdate,outfile_diagnostics,netcdf_cam_filename & 
        ,netcdf_clm_filename,netcdf_pop_filename & 
        ,netcdf_ice_filename,nx_CAM,ny_CAM,nz_CAM) 
    stop 
end program CAM_netcdf_to_WRF_intermediate 

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
SUBROUTINE HANDLE_ERR(STATUS) 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
    use netcdf 
    implicit none 
    INTEGER STATUS 
    IF (STATUS .NE. NF90_NOERR) THEN 
    PRINT *, NF90_STRERROR(STATUS) 
    STOP 'Stopped' 
    ENDIF 
END SUBROUTINE HANDLE_ERR 

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
Subroutine dummy_read & 
    (nz_WRF,outfile_diagnostics,netcdf_cam_filename & 
    ,netcdf_clm_filename,netcdf_pop_filename,netcdf_ice_filename & 
    ,nx_CAM,ny_CAM,nz_CAM) 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
    use netcdf 
    implicit none 
    integer :: nz_WRF 
    integer :: nx_CAM,ny_CAM,nz_CAM 
    character(len=128) :: filename 
    character(len=24) :: HDATE 
    integer :: outfile_diagnostics 
    integer :: STATUS, NCID, NCID_clm, NCID_pop, NCID_ice 
    character(len=128) :: netcdf_cam_filename, netcdf_clm_filename, netcdf_pop_filename 
    character(len=128) :: netcdf_ice_filename 

    ! open output files for metgrid in WRF/WPS intermediate format: 
    write(filename,'("Output/FILE:",A13)') hdate(1:13) 
    write(outfile_diagnostics,*) "output intermediate file filename=",filename 
    open(10,form='unformatted',file=filename) 

    write(filename,'("Output/SST:",A13)') hdate(1:13) 
    write(outfile_diagnostics,*) "output intermediate SST file filename=",filename 
    open(11,form='unformatted',file=filename) 

    STATUS = NF90_OPEN(netcdf_cam_filename, 0, NCID) 
! STATUS = NF90_OPEN(path = "Inputdata/ind/cam_CCSM4_historical_197909-197912-1979090100.nc", mode= 0, ncid = NCID) 
    IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS) 
print *, "first status conditional statement" 
    STATUS = NF90_OPEN(netcdf_clm_filename, 0, NCID_clm) 
    IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS) 
    STATUS = NF90_OPEN(netcdf_pop_filename, 0, NCID_pop) 
    IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS) 
    STATUS = NF90_OPEN(netcdf_ice_filename, 0, NCID_ice) 
    IF (STATUS .NE. NF90_NOERR) CALL HANDLE_ERR(STATUS) 
    status=NF90_CLOSE(NCID) 
    status=NF90_CLOSE(NCID_clm) 
    status=NF90_CLOSE(NCID_pop) 
    status=NF90_CLOSE(NCID_ice) 

print *, "Leaving dummy, going to MAIN" 
    return 
end Subroutine dummy_read 

如果我對netcdf文件的路徑進行硬編碼(請參見dummy_read子例程中的註釋掉的行),open語句將起作用。在main中打印netcdf_cam_filename會返回一個有效的字符串,但是在dummy_read子例程中輸出字符串將返回一個空字符串。我不確定爲什麼netcdf_cam_filename字符串沒有正確地將其設置到子例程中。

請詢問您是否需要更多信息。我只發佈了一些我認爲適用於該錯誤的代碼。提前致謝。

+0

使用'-g -traceback'獲得更有用的回溯。 – 2014-09-18 18:39:15

+0

使用-g -traceback不會提供其他信息。 – user2030765 2014-09-18 18:57:24

+0

馬克 - 我不確定你的意思 - fortran函數'nf90_open'不在代碼中,但加載了這個語句('use netcdf')。 – user2030765 2014-09-18 19:04:07

回答

4

您的子程序調用與實際定義不匹配。

您對dummy_read電話是:

call dummy_read(nz_WRF,hdate,outfile_diagnostics,netcdf_cam_filename & 
       ,netcdf_clm_filename,netcdf_pop_filename & 
       ,netcdf_ice_filename,nx_CAM,ny_CAM,nz_CAM) 

當你的dummy_read聲明:

Subroutine dummy_read & 
(nz_WRF,outfile_diagnostics,netcdf_cam_filename & 
,netcdf_clm_filename,netcdf_pop_filename,netcdf_ice_filename & 
,nx_CAM,ny_CAM,nz_CAM) 

或者顯示方式不同:

call  dummy_read(nz_WRF,hdate,    outfile_diagnostics,netcdf_cam_filename,netcdf_clm_filename,netcdf_pop_filename,netcdf_ice_filename,nx_CAM,ny_CAM,nz_CAM) 
Subroutine dummy_read(nz_WRF,outfile_diagnostics,netcdf_cam_filename,netcdf_clm_filename,netcdf_pop_filename,netcdf_ice_filename,nx_CAM,    ny_CAM,nz_CAM) 

導致參數不匹配。虛擬參數outfile_diagnostics與實際參數hdate等關聯。你逝去的10個參數來聲明一個子程序採取9


你可能會奇怪,爲什麼編譯器產生在這種情況下的可執行文件,而不是產生一個錯誤。這是因爲您使用隱式接口調用過程,Fortran相信您做的是正確的事情。 Fortran可以檢測參數不匹配,但要做到這一點,您需要提供明確的接口。除了顯式聲明接口之外,最簡單的方法是將過程作爲模塊過程(通過將子例程放入模塊中)或內部過程(通過在contains語句之後將過程放入主程序中)。

您還可以要求編譯器提供高級別的警告以避免此問題。與gfortran編譯與-Wall產生此警告與您的代碼:

 call dummy_read(nz_WRF,hdate,outfile_diagnostics,netcdf_cam_filename & 
          1 
Warning: Type mismatch in argument 'outfile_diagnostics' at (1); passed CHARACTER(1) to INTEGER(4) 

Adiitionally,ifort提供選項-gen-interfaces標誌,會自動生成模塊包含外部程序。不過,我認爲這是一個幫助將代碼移植到更新的語言標準而不是依靠的東西的工具。

+0

@ casey-謝謝。這似乎解決了這個問題。 – user2030765 2014-09-18 21:28:15

+2

+1我會補充說,如果子程序被放置在模塊中或者是程序內部的一個內部程序,則不會發生這種情況。 – 2014-09-18 21:28:37