2016-02-19 18 views
2

我在使用gfortran:GNU Fortran(Ubuntu 4.8.4-2ubuntu1〜14.04.1)4.8.4在linux上。包中的子程序ignpoi ranlib.f壞了

我試圖使用ignpoiranlib.f此源http://www.netlib.org/random/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 

具有相同的平均值後,在一個或多個d後出現分段故障eviates。

  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

啓用由'調試符號和簡單的檢查gfortran -g -fbacktrace -Wall -check = all'並報告你的發現。您可能需要顯示完整的代碼。 –

回答

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

不幸的是,相當多的後續計算/分支取決於所提到的變量,這導致了雙重隨機行爲。

我不知道在你的情況下發生段錯誤的位置,在我的機器上,我最終產生了一個無限循環。最簡單的解決方案是禁用存儲舊值。對於這一點,註釋(或刪除)的線(144 & 219)

 muold = mu 

或者,禁用跳過初始化(L 218):

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

謝謝! ranlib.f中是否還有其他已知的問題?另外,Fortran中的隨機數生成器(與gfortran兼容)有哪些替代「包」?我需要泊松,真正的統一,整數均勻,二項和高斯。 – wallace1837

+0

@ wallace1837對不起,我對ranlib.f沒有任何經驗,我的答案純粹來自分析'ignpoi.f'。對於我所有涉及隨機的項目(很少),random_number()都足夠了。 –