Debugging 与派生类型相关的Fortran分段错误

Debugging 与派生类型相关的Fortran分段错误,debugging,segmentation-fault,fortran,derived-types,Debugging,Segmentation Fault,Fortran,Derived Types,我在调试网格生成算法中出现的分段错误时遇到了一些严重的问题。不幸的是,我不能提供一个最低限度的工作示例。我想如果可以的话,我自己解决这个问题已经走了一半。所以基本上我希望有人能就我面临的问题分享一些想法。 来自分段错误的错误消息 forrtl: severe (174): SIGSEGV, segmentation fault occurred Image PC Routine Line Source

我在调试网格生成算法中出现的分段错误时遇到了一些严重的问题。不幸的是,我不能提供一个最低限度的工作示例。我想如果可以的话,我自己解决这个问题已经走了一半。所以基本上我希望有人能就我面临的问题分享一些想法。 来自分段错误的错误消息

forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image              PC                Routine            Line        Source            
gabel_v112         000000000054A346  Unknown               Unknown  Unknown
gabel_v112         0000000000544C2C  Unknown               Unknown  Unknown
gabel_v112         00000000005093DB  Unknown               Unknown  Unknown
gabel_v112         000000000040103C  Unknown               Unknown  Unknown
gabel_v112         000000000048E3F0  Unknown               Unknown  Unknown
gabel_v112         0000000000400F17  Unknown               Unknown  Unknown
通过使用回溯、英特尔调试器和一些老式的写入(,),我认为我能够在以下子例程中缩小分段错误的来源:

SUBROUTINE create_type_12(l)

    use types
    use parameters
    use vars_and_data

    implicit none

    INTEGER(I4B), INTENT(IN) :: l
    INTEGER(I4B) :: b, nl, neighbor, n_11

    do b=1, nf(l)
        if(levels(l)%blocks(b)%state .EQ. state_interface_undecided) then
            n_11 = 0
            do nl=1, nlinks
                neighbor = levels(l)%blocks(b)%neighbors(nl)
                if(neighbor .GT. 0) then
                    if(levels(l)%blocks(neighbor)%state .EQ. state_fine1) n_11 = n_11 + 1
                end if
            end do
            if(n_11 .GT. 0) levels(l)%blocks(b)%state = state_fine2
        end if
    end do

END SUBROUTINE create_type_12
更准确地说,这条线

if(levels(l)%blocks(neighbor)%state .EQ. state_fine1) n_11 = n_11 + 1
此子例程操作的数据结构定义如下:

TYPE :: blockinfo
    INTEGER(I4B)                :: number
    INTEGER(I4B)                :: state
    INTEGER(I4B)                :: state_floodfill
    INTEGER(I4B)                :: state_proximity
    INTEGER(I4B), DIMENSION(26) :: neighbors
    INTEGER(I4B), DIMENSION(26) :: linktype
    INTEGER(I4B)                :: parent
    INTEGER(I4B), DIMENSION(8)  :: children
    INTEGER(I4B), DIMENSION(3)  :: pos
    INTEGER(I4B)                :: triangle_amount
    INTEGER(I4B)                :: triangle_ll
END TYPE blockinfo

TYPE :: block
    TYPE(blockinfo), DIMENSION(:), ALLOCATABLE :: blocks
END TYPE block

TYPE(block), DIMENSION(:), ALLOCATABLE :: levels
现在麻烦就从这里开始了。通常,我会使用-check边界进行编译,以确定分段错误的来源。不幸的是-check限制代码正常运行并生成有效的结果数据集。我使用的其他编译器标志是-O3-xSSE4.2-ipo-static-asked buffered_io。Ifort编译器版本为16.0.1和13.1.3。验证了不同机器上的行为

更糟糕的是,如果我更改一些编译标志(例如省略-xSSE4.2),代码运行良好。但是,单独使用-xSSE4.2而不进行任何其他优化,代码也可以正常运行。切换到带有“相似”编译标志的gfortran,代码也可以正常运行

通过进一步调试,我发现当变量b的值为27388461时,就会出现分段错误。但令我惊讶的是,所有级别(l)%blocks(27388461)%neighbor的值都在blocks(这里是102883584)的大小范围内,当然除了负数。所以我不知道是什么导致了分割错误

长话短说,我有三个问题,但欢迎任何其他提示:

  • 我在这里使用派生类型的方式有什么明显的错误吗
  • 我可以做些什么来进一步缩小分段故障的来源
  • 如果我几天前还没有想好的话,我真的不会问这个问题:是否有任何已知的英特尔fortran编译器错误与派生类型有关
  • 我知道这种类型的“问题”可能不适合堆栈溢出,但我希望有人能给我一个有用的提示

    编辑:问题3的答案似乎是“是”。 正如Jim Dempsey在英特尔Fortran论坛上指出的那样:

    您的blockinfo类型有70个整数(4)变量或280个字节。当变量b的值为27388461。。。 27388461*280=7668769080=0x1C9182138 IOW需要33位。某些版本的IVF使用索引变量的精度来构造元素的字节偏移量


    使用8字节整数作为“blocktype”派生类型的索引似乎是一种可能的解决方法。但是,为了避免一个出现在几年后的编译器错误,我宁愿考虑切换到一个不同的编译器。

    如果调试改变了行为,考虑堆栈损坏是一个很好的选择。检查是否使用正确的参数类型和数组大小调用所有子例程和函数。问题可能在崩溃发生的地方以外的其他地方。应该使用-gen接口和-warn接口吗?我已经试过了,但是没有用。这取决于,如果在不同的文件中有对外部过程的调用,它可能不会被检测到。如果你想让我们回答你的问题,你必须准备一个mcve(1)你所有的类型都是动态的——你总是检查分配吗?一切都初始化正确吗?像您报告的编译相关错误可能会暴露这类错误。请记住,错误可能远远看不到其原因。(2) 既然您找到了错误,那么打印所有涉及变量(首先是大小)的所有信息应该会给您带来一些好处(从
    nf
    开始)。这很严重(174)。。。程序尝试了无效的内存引用--它发生在某个地方。正如Vladimir F所说,仅仅是思考,就需要更多的代码。如果调试改变了行为,那么最好考虑堆栈损坏。检查是否使用正确的参数类型和数组大小调用所有子例程和函数。问题可能在崩溃发生的地方以外的其他地方。应该使用-gen接口和-warn接口吗?我已经试过了,但是没有用。这取决于,如果在不同的文件中有对外部过程的调用,它可能不会被检测到。如果你想让我们回答你的问题,你必须准备一个mcve(1)你所有的类型都是动态的——你总是检查分配吗?一切都初始化正确吗?像您报告的编译相关错误可能会暴露这类错误。请记住,错误可能远远看不到其原因。(2) 既然您找到了错误,那么打印所有涉及变量(首先是大小)的所有信息应该会给您带来一些好处(从
    nf
    开始)。这很严重(174)。。。程序尝试了无效的内存引用--它发生在某个地方。正如Vladimir F所说,为了更好,需要更多的代码。