包ranlib.f中的子例程ignpoi被破坏了

时间:2016-02-19 20:30:44

标签: random fortran gfortran numerical-methods

我在linux上使用gfortran:GNU Fortran(Ubuntu 4.8.4-2ubuntu1~14.04.1)4.8.4。

我正在尝试使用此来源http://www.netlib.org/random/中的ignpoi ranlib.f http://www.netlib.org/random/ranlib.f.tar.gz

我使用

编译库
   gfortran -O2 -c *.f
   ar cr libranlib.a *.o

当我编写简单的程序来测试ignpoi(泊松偏差发生器)

  program test
  implicit none
  integer seed1, seed2, i
  real av
  integer ignpoi

  seed1=123456
  seed2=654321
  call setall(seed1,seed2)

  av=8.0
  do i=1,10
     print *, ignpoi(av)
  enddo

  end

具有相同的平均值,在一个或多个偏差后给出分段错误。

          12
           7

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7F077F1D3E48
#1  0x7F077F1D2FD0
#2  0x7F077E9042EF
#3  0x401288 in ignpoi_
#4  0x400A3D in MAIN__ at test.f:?
Segmentation fault (core dumped)

这是我编译测试时没有编译错误的方法。

gfortran test.f libranlib.a

奇怪的是,当我每次都要求不同的号码时,没有问题。当我评论第104-105行

IF (mu.EQ.muprev) GO TO 10     
IF (mu.LT.10.0) GO TO 120
ignpoi.f

,问题就消失了。

这可以复制吗?

导致错误的原因是什么?

我得到104-105行是为了节省计算时间。如何修改当前函数以从预计算中受益而没有调用具有相同平均多次的函数的问题?

1 个答案:

答案 0 :(得分:1)

嗯,那个特定的代码被破坏......在ignpoi.f中,ll。 218:

      IF (mu.EQ.muold) GO TO 130
      muold = mu
      m = max0(1,ifix(mu))
      l = 0
      p = exp(-mu)
      q = p
      p0 = p
C
C     STEP U. UNIFORM SAMPLE FOR INVERSION METHOD
C
  130 u = ranf()

第一个条件为真,因此您跳过mlpqp0的初始化。在这些变量中,之前仅触及l - 但mu == muold也会跳过此变量。

不幸的是,相当多的后续计算/分支取决于所提到的变量,这导致 - 借口双关语 - 随机行为。

我不知道在你的情况下发生了segfault的位置,在我的机器上我最终得到了无限循环。最简单的解决方案是禁用存储旧值。为此,注释掉(或删除)行(144& 219)

      muold = mu

或者,禁用跳过初始化(l.218):

C     IF (mu.EQ.muold) GO TO 130