2010-08-24 86 views
2

我正在使用mex鏈接一些fortran代碼(f90)從matlab,我偶爾有matlab凍結。強制顯式變量聲明與gfortran

過去,由於數據類型不匹配(例如整數* 4與整數* 8),我發生了凍結。

我連接的代碼有許多隱式定義的變量,所以我想知道是否有偶爾出現的隱藏數據類型衝突。

要排除數據類型不匹配的原因凍結,我希望編譯器要求顯式聲明所有變量。

問題:

  1. 我怎麼gfortran需要在編譯時明確聲明的所有變量?如果沒有,有沒有辦法至少得到警告?

  2. gfortran是否將「真實」數據類型解釋爲所有體系結構中的特定種類?如果是這樣,哪一個(真實* 4,真實* 8,...)?

  3. 有沒有辦法強迫gfortran將「真實」數據類型解釋爲特定類型,比如說「真實* 4」?

  4. 有什麼想法讓fortran代碼在從matlab中的mex編譯例程中調用時凍結(數據類型不匹配除外)?

感謝您的任何幫助。

直到我明白了這一點,我會經歷許多代碼行,試圖列出所有隱式定義的變量。 不用說,我將大大感激的人誰解放了我從這麼無聊的任務......

最佳,

G.

回答

1
  1. 您可以要求通過添加implicit none明確聲明所有變量。
  2. 我相信默認的「真實」數據類型是real*4
  3. 您可以使用命令行標誌,-fdefault-real-8迫使聲明爲real所有變量被解釋爲real*8

注(寫更多的代碼,不一定試圖解決當前的bug): 如果您正在使用Fortran 90代碼,可以使用real(kind=4)real(kind=8)與gfortran,而不是real*4real*8語法。我已經不再使用命令行標誌設置實數或整數大小,而是使用一個integer, parameter :: REAL_SIZE變量來保存適當的數字(我通常選擇4或8,因爲我使用的所有編譯器都支持它們,但是如果您想要非常便攜,您應該使用selected_real_kind例程)

+0

非常感謝,特別是關於-fdefault-real-8標誌的提示。你知道是否還有一個-fdefault-real-4標誌嗎?我在gfortran上嘗試過,但它似乎沒有工作...... – gvrocha 2010-08-24 19:40:13

+0

我不這麼認爲,因爲那只是默認設置。 – 2010-08-24 19:52:09

+0

所以真正的默認值不是架構依賴呢? – gvrocha 2010-08-24 19:57:49

0

其中一個適用於大多數編譯器,因爲Fortran 77的:

implicit none 

implicit undefined(a-z) 

Real是架構相關的;默認大小通常可以通過命令行選項進行修改。

我沒有任何與Matlab連接的經驗。

+0

感謝您的快速回復。 – gvrocha 2010-08-24 19:40:28

2

如前所述,在您的源代碼中,您可以使用隱式無。優點是這對所有編譯器都是可移植的。

使用gfortran,您可以使用編譯器選項-fimplicit-none。這個好處是,它會捕獲你忘記明確鍵入的變量,即使你忘記了包含隱含的沒有。其他大多數編譯器都有類似的選項。

這兩個都是強烈推薦 - 隱式類型是有害的,並允許錯字錯誤創建意想不到的變量。

簡單的「真實」意味着什麼取決於編譯器 - 如果您有特定要求,最好使用更具體的聲明。最好的方法是用選定的真實類型內在定義一個參數並使用它 - 對於類似的討論,請參見Fortran: integer*4 vs integer(4) vs integer(kind=4)

+0

非常感謝,特別是針對-fimplicit-none標誌 – gvrocha 2010-08-24 19:39:27

+0

+1的提示,尤其是對於編譯器選項。 – Wildcat 2010-08-24 20:38:15

2

IMPLICIT NONE和編譯器選項已經提到。

讓我們來談談浮點運算。問題在於(MATLAB提到的here)MATLAB根據IEEE® Standard 754構造了雙精度(或雙精度)和單精度(或單精度)數據類型,但Fortran標準並不要求它是默認的,雙精度實數來符合這個標準。正如您可以看到標準文檔甚至使用其他名稱(默認爲真,而不是單精度)。

MODULE kinds 

    IMPLICIT NONE 

    INTEGER, PARAMETER :: fortran_default = kind(0.0) 
    INTEGER, PARAMETER :: fortran_double = kind(0.0D0) 
    INTEGER, PARAMETER :: ieee_single = selected_real_kind(7, 38) 
    INTEGER, PARAMETER :: ieee_double = selected_real_kind(15, 307) 

END MODULE kinds 

在我的種規格的前兩個字符串中,我用方便的方法來獲得默認實數和雙精度實數的種類。接下來的兩種對應於提到的IEEE標準。

PROGRAM main 

    USE kinds 

    IMPLICIT NONE 

    REAL(kind=ieee_single) :: is 
    REAL(kind=ieee_double) :: id 
    REAL(kind=fortran_default) :: fs 
    REAL(kind=fortran_double) :: fd 

    PRINT *, kind(is), precision(is), range(is) 
    PRINT *, kind(id), precision(id), range(id) 
    PRINT *, kind(fs), precision(fs), range(fs) 
    PRINT *, kind(fd), precision(fd), range(fd) 

END PROGRAM main 

我的機器(的Mac OS X 10.6,gfortran 4.5.1)上的輸出是:

8   15   307 
    8   15   307 
    4   6   37 
    8   15   307 

所以Fortran語言的默認實樣不等於IEEE標準的單精度浮點數的那種。

所以它可能是錯誤的來源。精度在某處丟失,某些變量等於0.0,而不是略大於0.0,然後除以該值(正好爲0.0)。那麼,它可以凍結該程序。

+1

觀察>>猜測 - 非常好。 – 2010-08-24 20:39:25

+2

技術上,selected_real_kind(7,38)提供至少7位精度 - 如果編譯器選擇它可以提供更多精度,所以這不能保證選擇IEEE類型。如果您絕對必須擁有IEEE類型,則有Fortran 2003的新IEEE模塊 - 但尚未普遍支持。 – 2010-08-24 20:59:41

+0

@ M. S. B .:您的評論完全有效。這個想法是讓Fortran代碼中的浮點數的精度至少達到IEEE的單精度和雙精度。 – Wildcat 2010-08-25 07:38:39