我在调试网格生成算法中出现的分段错误时遇到了一些问题。不幸的是,我无法提供最小的工作示例。我想如果可以的话,我会在中途解决这个问题。所以基本上我希望有人可以就我面临的问题分享一些想法。 分段错误的错误消息
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),当然除了负面的。所以我不知道这可能导致分段错误。
长话短说我有三个问题,但欢迎任何其他提示:
我知道这种类型的“问题”可能不适合堆栈溢出,但我希望有人可以给我一个有用的提示。
编辑:问题3的答案似乎是“是”。 正如Jim Dempsey在英特尔Fortran论坛中指出的那样:
您的blockinfo类型有70个整数(4)变量或280个字节。当变量b的值为27388461时...... 27388461 * 280 = 7668769080 = 0x1C9182138 IOW需要33位。某些版本的IVF使用索引变量的精度来构造元素的字节偏移量。
使用8字节整数作为“blocktype”派生类型的索引似乎是一种可能的解决方法。但是,不是改变整个代码以避免出现多年来出现的编译器错误,而是考虑切换到不同的编译器。