【问题标题】:Very simple program in fortran giving me a segmentation fault. Very confusedfortran 中非常简单的程序给了我一个分段错误。很迷茫
【发布时间】:2012-10-14 15:31:03
【问题描述】:

我一直在疯狂地尝试在我的简单程序中将一些数据读入数组。我无法弄清楚为什么会出现分段错误。我的代码开始:

program guess_input
implicit none

CHARACTER*2, allocatable, dimension(:) :: element
double precision, allocatable, dimension(:,:)      :: xyzq
INTEGER, allocatable, dimension(:)                 :: label,cs_num, br_num, xx_num
real, allocatable, dimension(:)                    :: distance
real, allocatable, dimension(:)                    :: ep
INTEGER                                :: stat, numatom, i, j
CHARACTER*80  :: line

numatom = 61502
allocate(element(numatom))
allocate(xyzq(4,numatom))
allocate(label(numatom))

OPEN(UNIT=22,FILE='EMBQ_EPF.OUT',iostat=stat)
If(stat.ne.0) Stop "File not found"

!Read in the input into two arrays

do i=1,numatom
READ(22,'(A)') line
READ(line, *) xyzq(1,i), xyzq(2,i), xyzq(3,i), xyzq(4,i), label(i)
enddo
CLOSE(22)

!Define element type in parallel array based on the charge 
do i=1,numatom
if(xyzq(4,i) == 1.00) then
            element(i) = 'Cs'
elseif(xyzq(4,i) == -1.00) then
            element(i) = 'Br'
else
        element(i) = 'XX'
    endif
 enddo

 OPEN(33, FILE='element.out')
 do i=1,numatom
 write(33,*) element(i)
 enddo

 end program guess_input

我已经尝试隔离故障,但我真的无法弄清楚出了什么问题。

任何帮助将不胜感激,谢谢。

【问题讨论】:

  • 如果没有输入文件就很难猜到。我生成了一些假输入(在 python 中:for i in xrange(61502): fd.write("%d\t%d\t%d\t%d\t%s\n" % (1, -1, -1, -1+i%5, '22'))),工作正常。
  • 你能告诉我们它发生在哪一行吗?使用 GDB 什么的?
  • 由于您只发布了部分代码并且您还没有确定发生分段错误的行或块,您能否向我们保证您发布的片段会导致分段错误,以便我们不会'不要浪费我们的时间在错误的地方寻找故障。

标签: segmentation-fault fortran


【解决方案1】:

如果您还没有准备好,我建议使用运行时下标检查进行编译。分段错误的一个可能原因是下标错误。在调试过程中使用最大编译器诊断很有帮助。使用 gfortran:-O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck=all -std=f2008 -pedantic -fbacktrace。使用 ifort:-O2 -stand f03 -assume realloc_lhs -check all -traceback -warn all -fstack-protector -assume protect_parens -implicitnone-fcheck=all-check all 包括运行时下标检查;如果需要,可以只选择运行时下标检查 -- 请参阅编译器文档。

另外:与浮点值进行精确比较是有风险的。我建议将 xyzq 转换为整数变量或测试到一个范围:

if( abs (xyzq(4,i) - 1.00) < 0.01 ) then

【讨论】:

  • 1.0 在单精度和双精度 IEEE 745 中完全可以表示,但您的注释仍然适用。 +1
【解决方案2】:

要查找分段错误的原因,您可以使用Valgrindmemcheck 工具。语法很简单:

valgrind --tool=memcheck --leak-check=full <binary> <arguments>

此工具应为您提供源代码中出现memory-management problems 的确切行。

【讨论】:

  • 与 C/C++ 不同,Fortran 不会丢失内存分配的跟踪,并且大多数 F90+ 实现使用数组描述符,这允许它们在必要时执行运行时边界检查。在这种情况下使用valgrind 有点过头了。
【解决方案3】:

您的编译器是否足够聪明,可以知道您的意思是“numatom”和“i”是 4 字节整数?如果不是,并且假设您的意思是“INTEGER”为 2 字节长,那么您将进入负内存空间的神秘世界。

【讨论】:

  • 虽然 Fortran 标准没有指定默认 INTEGER 种类的大小,但我怀疑现代 Fortran 处理器默认使用 16 位整数(除非他使用一些旧的 16 -bit DOS 处理器...)
猜你喜欢
  • 2015-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
  • 2014-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多