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

时间:2016-05-25 16:34:24

标签: debugging segmentation-fault fortran derived-types

我在调试网格生成算法中出现的分段错误时遇到了一些问题。不幸的是,我无法提供最小的工作示例。我想如果可以的话,我会在中途解决这个问题。所以基本上我希望有人可以就我面临的问题分享一些想法。 分段错误的错误消息

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

使用traceback,intel调试器和一些老式的写()我认为我能够在以下子例程中缩小分段错误的起源:

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 bounds编译来确定分段错误的起源。不幸地,使用-check bounds代码正常运行并生成有效的结果数据集。我使用的其他编译器标志是-O3 -xSSE4.2 -ipo -static -assume buffered_io。 Ifort编译器版本是16.0.1和13.1.3。验证了不同机器上的行为。

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

做一些调试我发现当变量b的值为27388461时会发生分段错误。但令我惊讶的是,所有级别的值(l)%块(27388461)%邻居都在块的大小范围内(这里是102883584),当然除了负面的。所以我不知道这可能导致分段错误。

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

  1. 我在这里使用派生类型的方式有什么明显错误吗?
  2. 我该怎么做才能进一步缩小分段错误的起源?
  3. 如果我几天前没有用完想法,我真的不会问这个问题:是否有与衍生类型相关的已知intel fortran编译器错误?
  4. 我知道这种类型的“问题”可能不适合堆栈溢出,但我希望有人可以给我一个有用的提示。

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

      

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

    使用8字节整数作为“blocktype”派生类型的索引似乎是一种可能的解决方法。但是,不是改变整个代码以避免出现多年来出现的编译器错误,而是考虑切换到不同的编译器。

0 个答案:

没有答案