Arrays 建模中的时间数组越界?

Arrays 建模中的时间数组越界?,arrays,fortran,bounds,Arrays,Fortran,Bounds,这些天我试图用新的气象数据运行我的气候模型(以netcdf格式而不是旧的cray格式给出)。模型的编译是顺利的,但是,当进行模拟时,模型在第一天运行良好,但在模拟的第二天停止,始终处于同一时间步,无论我使用什么开始日期。错误是: forrtl:severe(408):fort:(2):数组TIMEVALS的下标#1的值141大于140的上限 所以我做了一些研究,并浏览了我的源代码,看看timevals指的是什么样的数组,我发现它指的是这个新的气象数据,它有一个时间维度,这种时间数组由140个元素

这些天我试图用新的气象数据运行我的气候模型(以netcdf格式而不是旧的cray格式给出)。模型的编译是顺利的,但是,当进行模拟时,模型在第一天运行良好,但在模拟的第二天停止,始终处于同一时间步,无论我使用什么开始日期。错误是:

forrtl:severe(408):fort:(2):数组TIMEVALS的下标#1的值141大于140的上限

所以我做了一些研究,并浏览了我的源代码,看看timevals指的是什么样的数组,我发现它指的是这个新的气象数据,它有一个时间维度,这种时间数组由140个元素组成。每个元素都是模型用于模拟的气象数据的特定日期和时间…因此我开始认为这是我的代码的问题,但我的同事能够毫无问题地运行模型,这对我来说很奇怪。他使用Makefile中的一些不同设置编译了模型,我不知道这是否重要,我仍然不太熟悉fortran等。但是下面是使用此TIMEVALS数组的部分代码:

           CASE(2)        ! nudging data is in netcdf-format

           cfile = str_filter(ndg_file_nc,yr,mo,dy,hr,mi,se,ndgblock)
           CALL message('   Adjust date using file: ',TRIM(cfile))

           IF (p_parallel_io) THEN
             INQUIRE(file=cfile,exist=found)
             IF (.NOT.found) &
                CALL finish('NudgingInit','Nudging data file not found.')
             ndgfile%format = NETCDF
             CALL IO_open (cfile, ndgfile, IO_READ)
             CALL IO_INQ_DIMID(ndgfile%file_id, 'time', ndimid)
             CALL IO_INQ_DIMLEN(ndgfile%file_id, ndimid, nts)
             CALL IO_INQ_VARID(ndgfile%file_id, 'time', nvarid)
             ALLOCATE (timevals(nts))
             CALL IO_GET_VAR_DOUBLE (ndgfile%file_id, nvarid, timevals)
             ihead_nc(1) = FLOOR(timevals(1))                          ! ihead_nc(1) is YYYYMMDD
             ihead_nc(2) = INT((timevals(1)-ihead_nc(1))*24._dp)       ! ihead_nc(2) is HH
             DEALLOCATE (timevals)
           ENDIF

           IF (p_parallel) CALL p_bcast(ihead_nc, p_io)
           CALL inp_convert_date(ihead_nc(1),ihead_nc(2)*10000, ndg_date0)

             IF (p_parallel_io) THEN
             ! skip first record and read second header
             ALLOCATE (timevals(nts))
             CALL IO_GET_VAR_DOUBLE (ndgfile%file_id, nvarid, timevals)
             ihead_nc(1) = FLOOR(timevals(2))                          ! ihead_nc(1) is YYYYMMDD
             ihead_nc(2) = INT((timevals(2)-ihead_nc(1))*24._dp)       ! ihead_nc(2) is HH
             DEALLOCATE (timevals)
             CALL IO_close(ndgfile)
           ENDIF

           IF (p_parallel) CALL p_bcast(ihead_nc, p_io)
           CALL inp_convert_date(ihead_nc(1),ihead_nc(2)*10000, ndg_date1)
ndg_文件
ndg_日期
请参阅轻推(气象数据)
你们知道是什么导致了这个错误吗?

我现在有时间详细阐述一下我之前的评论。(请注意,我使用斜体表示您可能需要阅读的术语。)

您报告的错误是运行时错误,而不是编译器在编译时能够看到的错误。如果您不理解运行时(即代码执行时)和编译时(即编译器将源代码转换为可执行代码时)之间的区别,请进行一些研究。此外,很明显,您(或其他人)已指示编译器创建一个版本的代码,用于检查数组元素访问是否在数组边界内。在测试新软件时,这是一个非常重要的安全特性,但是如果代码执行了太多的代码,一旦它们通过了测试,在编译时没有进行此检查,则会造成性能损失

我不知道您使用的是什么编译器,但请查看它的文档,找到一个在运行时启用数组边界检查的选项

错误消息非常明确——在代码中的某个时刻,它试图访问只有140个元素的数组的元素141。我们无法告诉您这是如何发生的,即使我们看到了您的全部代码,也可能无法告诉您。当加载的数据不符合程序员的期望时,通常会发生这种情况。当程序员在编写循环时出现一个接一个的错误时,这种情况也经常发生。从您的整个代码中,我们可能会发现这一点,但您的处境比我们好得多

你写

但我的同事已经能够毫无问题地运行该模型,这 这对我来说很奇怪。他用一些不同的设置编译了这个模型 在Makefile中,我不知道这是否重要

嗯,是的,这很重要,非常重要。如果您编写的代码使用140个元素访问数组的元素141,Fortran与许多其他编译语言一样,将很乐意访问元素140之后的内存中的下一个位置。一般来说,您不知道程序正在干扰哪些数据。如果幸运的话,内存中的下一个位置在操作系统分配给程序的地址空间之外,操作系统会立即停止程序并报告分段故障

如果你运气不好,程序会愉快地读取和写入元素141,不管它是什么

我推测您的同事尚未为其版本的代码实现数组边界检查。这取决于你是否告诉他他的密码(很可能)坏了


那你怎么办?你调试程序。您可以通过多种方式来实现这一点,最简单的方法是(在我看来)插入一些
write
语句,在代码中的关键点打印变量值,以测试您对它们可能、可能或实际取值的假设。更困难的是,在调试器的控制下运行代码,但在未来的问题解决方面值得付出初步努力。在所有主要的平台上,Fortran程序都有几种很好的调试器可用。

我现在有时间详细阐述我先前的评论。(请注意,我使用斜体表示您可能需要阅读的术语。)

您报告的错误是运行时错误,而不是编译器在编译时能够看到的错误。如果您不理解运行时(即代码执行时)和编译时(即编译器将源代码转换为可执行代码时)之间的区别,请进行一些研究。此外,很明显,您(或其他人)已指示编译器创建一个版本的代码,用于检查数组元素访问是否在数组边界内。在测试新软件时,这是一个非常重要的安全特性,但是如果代码执行了太多的代码,一旦它们通过了测试,在编译时没有进行此检查,则会造成性能损失

我不知道您使用的是什么编译器,但请查看它的文档,找到一个在运行时启用数组边界检查的选项

错误消息非常明确——在代码中的某个时刻,它试图访问只有140个元素的数组的元素141。我们无法告诉您这是如何发生的,即使我们看到了您的全部代码,也可能无法告诉您。当加载的数据不符合程序员的期望时,通常会发生这种情况。当程序员在编写循环时出现一个接一个的错误时,这种情况也经常发生。从您的整个代码中,我们可能会发现这一点,但您的处境比我们好得多