Fortran排序方法数值配方

时间:2014-04-29 09:29:40

标签: sorting segmentation-fault fortran fortran77

我使用C来调用Fortran, 我的fortran正在调用sort()方法

 *-----------------------------------------------------------------------
 * SUBROUTINE sort(A,n)
 * Subroutine de la librairie "Numerical Recipes"
 * (C) Copr. 1986-92 Numerical Recipes Software
 *-----------------------------------------------------------------------
      SUBROUTINE sort(arr,n)
      INTEGER n,M,NSTACK
      REAL arr(n)
      PARAMETER (M=7,NSTACK=50)
      INTEGER i,ir,j,jstack,k,l,istack(NSTACK)
      REAL a,temp
      jstack=0
      l=1
      ir=n
1     if(ir-l.lt.M)then
        do 12 j=l+1,ir
          a=arr(j)
          do 11 i=j-1,1,-1
            if(arr(i).le.a)goto 2
            arr(i+1)=arr(i)
11        continue
          i=0
2         arr(i+1)=a
12      continue
        if(jstack.eq.0)return
        ir=istack(jstack)
        l=istack(jstack-1)
        jstack=jstack-2
      else
        k=(l+ir)/2
        temp=arr(k)
        arr(k)=arr(l+1)
        arr(l+1)=temp
        if(arr(l+1).gt.arr(ir))then
          temp=arr(l+1)
          arr(l+1)=arr(ir)
          arr(ir)=temp
        endif
        if(arr(l).gt.arr(ir))then
          temp=arr(l)
          arr(l)=arr(ir)
          arr(ir)=temp
        endif
        if(arr(l+1).gt.arr(l))then
          temp=arr(l+1)
          arr(l+1)=arr(l)
          arr(l)=temp
        endif
        i=l+1
        j=ir
        a=arr(l)
3       continue
          i=i+1
        if(arr(i).lt.a)goto 3
4       continue
          j=j-1
        if(arr(j).gt.a)goto 4
        if(j.lt.i)goto 5
        temp=arr(i)
        arr(i)=arr(j)
        arr(j)=temp
        goto 3
5       arr(l)=arr(j)
        arr(j)=a
        jstack=jstack+2
        if(jstack.gt.NSTACK)pause 'NSTACK too small in sort'
        if(ir-i+1.ge.j-l)then
         istack(jstack)=ir
         istack(jstack-1)=i
         ir=j-1
       else
         istack(jstack)=j-1
         istack(jstack-1)=l
         l=i
       endif
     endif
     goto 1
     END

如果我多次调用sort方法,我在这个方法中有一个段错误:(

这是遗留代码,但我相信它,因为它来自数字收件人。 但我对某些事情持怀疑态度,特别是这一行:

if(jstack.gt.NSTACK)pause 'NSTACK too small in sort'

如果我在这种情况下,我的程序会暂停? sort方法如何做到这一点?

如果这条线可疑,我怎么能相信整个代码?

有没有人知道这个排序子程序的问题?有没有人知道在fortran中进行排序的另一种方法?因为我可以用另一个替换这种排序方法,但我是fortran的新手,我不能写另一个。

我补充一点,如果我在单线程中运行此方法没有问题,但如果我在多线程环境中运行它,问题就在这里。很抱歉在我写我的问题时没有提到,但是在写完之后我就看到了。

调查信息

current thread: t@41
  [1] __lwp_kill(0x0, 0x6, 0x0, 0x6, 0xffbffeff, 0x0), at 0xff2caa58
  [2] raise(0x6, 0x0, 0xff342f18, 0xff2aa378, 0xffffffff, 0x6), at 0xff265a5c
  [3] abort(0x7400, 0x1, 0x0, 0xfcb78, 0xff3413d8, 0x0), at 0xff24194c
  [4] os::abort(0x1, 0x0, 0xff011084, 0xfefdc000, 0x7d94, 0x7c00), at 0xfee7d3cc
  [5] VMError::report_and_die(0x0, 0xff038640, 0xff031ff4, 0x1, 0xfee81b94, 0xff031ff4), at 0xfef0cd58
  [6] JVM_handle_solaris_signal(0xb, 0xacffefe0, 0xacffed28, 0x8000, 0xff030fa0, 0x2013d8), at 0xfea73d48
  [7] __sighndlr(0xb, 0xacffefe0, 0xacffed28, 0xfea7325c, 0x0, 0x1), at 0xff2c6e78
  ---- called from signal handler with signal 11 (SIGSEGV) ------
  [8] sort_(0xfe2b1350, 0xfe2b135c, 0xfe2b1000, 0x1c00, 0x443bfc7b, 0xfe292484), at 0xfe27e498
  [9] mediane_(0xa9c1624c, 0xacfff2ac, 0xa9c16060, 0xa9c05c34, 0x0, 0x19), at 0xfe27a38c


(dbx) frame 8
0xfe27e498: sort_+0x01d8:       ld       [%l4 + %l1], %f4
(dbx) disassemble
0xff2caa58: __lwp_kill+0x0008:  bcc,a,pt  %icc,__lwp_kill+0x18  ! 0xff2caa68
0xff2caa5c: __lwp_kill+0x000c:  clr      %o0
0xff2caa60: __lwp_kill+0x0010:  cmp      %o0, 91
0xff2caa64: __lwp_kill+0x0014:  move     %icc,0x4, %o0
0xff2caa68: __lwp_kill+0x0018:  retl
0xff2caa6c: __lwp_kill+0x001c:  nop
0xff2caa70: __lwp_self       :  mov      164, %g1
0xff2caa74: __lwp_self+0x0004:  ta       %icc,0x00000008
0xff2caa78: __lwp_self+0x0008:  retl
0xff2caa7c: __lwp_self+0x000c:  nop

在solaris中的m,dbx =>

上的gdb

我尝试检查地址,但我可以键入什么来获得有趣的信息?

在f90编译器中添加-g选项后,在dbx中我可以看到value或var并查看结果:

t@88 (l@88) terminated by signal ABRT (Abort)
0xff2caa58: __lwp_kill+0x0008:  bcc,a,pt  %icc,__lwp_kill+0x18  ! 0xff2caa68
Current function is sort
  578           temp=arr(k)
(dbx) print n
n = 19
(dbx) print arr
arr =
    (1)    725.0666
    (2)    741.5034
    (3)    730.8196
    (4)    754.3707
    (5)    741.718
    (6)    741.718
    (7)    741.8914
    (8)    745.9141
    (9)    744.6705
    (10)    741.718
    (11)    745.8358
    (12)    743.3788
    (13)    746.2706
    (14)    746.2706
    (15)    750.1498
    (16)    754.3707
    (17)    754.3707
    (18)    754.3707
    (19)    748.2084
(dbx) print istack
istack =
    (1)    7
    (2)    12
    (3)    17
    (4)    18
    (5)    8
    (6)    9
    (7)    1
    (8)    4
    (9)    0
    (10)    0
    (11)    0
    (12)    0
    (13)    0
    (14)    0
    (15)    0
    (16)    0
    (17)    0
    (18)    0
    (19)    0
    (20)    0
    (21)    0
    (22)    0
    (23)    0
    (24)    0
    (25)    0
    (26)    0
    (27)    0
    (28)    0
    (29)    0
    (30)    0
    (31)    0
    (32)    0
    (33)    0
    (34)    0
    (35)    0
    (36)    0
    (37)    0
    (38)    0
    (39)    0
    (40)    0
    (41)    0
    (42)    0
    (43)    0
    (44)    0
    (45)    0
    (46)    0
    (47)    0
    (48)    0
    (49)    0
    (50)    0
(dbx) print jstack
jstack = -31648
(dbx)

它可能的taht jstack有-31648 val! istack只有50个元素和istack(jstack)重新给我一个abd值!怎么可能? :) 谢谢提前

1 个答案:

答案 0 :(得分:0)

评论太大了:

不幸的是,堆栈跟踪没有显示确切的故障线。什么证据表明错误出现在您指定的行上。我可以想象在调用运行时系统时可能会出错,您应该尝试将PAUSE语句更改为writeread *,或类似内容。

我在gfortran中用你的子程序做了一些测试:

  parameter (n = 100000)
  dimension b(n)

  do i=1,1000
    call random_number(b)
    call sort(b,n)
  end do
end

具有不同的数组大小和循环边界。这会使sort调用许多不同的输入。我启用了所有检查和清理,并没有遇到任何问题。

修改

它也适用于OpenMP:

  parameter (n = 100000)
  real,allocatable :: b(:)

  !$omp parallel private(b)
  allocate(b(n))
  !$omp do
  do i=1,1000
    call random_number(b)
    call sort(b,n)
  end do
  !$omp end do
  !$omp end parallel
end