2013-10-01 36 views
0

所以我有一個程序,其中有這樣的事情在裏面:如果我在fortran中調用一個函數,而沒有定義一個變量,會發生什麼?

integer :: mgvn, stot, gutot, iprint, iwrit, ifail, iprnt 
... 
call readbh(lubnd,nbset,nchan,mgvn,stot,gutot,nstat,nbound,rr,bform,iprnt,iwrit,ifail) 

然後裏面readbh

 CALL GETSET(LUBND,NSET,KEYBC,BFORM,IFAIL) 
     IF(IFAIL.NE.0) GO TO 99 
     ... 
99 WRITE(IWRITE,98) NBSET,LUBND 
     IFAIL = 1 
     RETURN 

,所有的其它變量的定義,但ifail不是。如果我在函數調用之前添加write(*,*) ifail,我會得到未定義的變量錯誤,但是如果我忽略它,它不會發出抱怨,並且會隨函數一起運行,並且總是失敗,並且IFAIL=1

這是因爲它剛開在readbh函數的參數結束,讀取未初始化的內存 - 這僅僅是隨機jibberish - 然後鑄造那些位的int - 這不會是零,除非我'非常(非)幸運,所以幾乎總是讓ifail.ne.0true

+0

您是不是定義了ifail,還是將它從調用參數列表中刪除?訪問一個未定義的變量就是未定義的。它可能爲零,或者可能是垃圾發生在該內存位置。如果您訪問的子程序中甚至沒有提供的參數,您可能會遇到seg故障。 – agentp

+0

「-Wuninitialized」標誌有一個原因...... –

回答

1

我會選擇來解釋你叫什麼未定義的變量作爲未初始化變量。一般來說,Fortran和許多其他編譯的編程語言,都會非常高興地使用未初始化的變量進行計算。它/它們是成年人的編程語言,如果你編程這種行爲,它是在我們自己的頭上。編寫一個使用未初始化變量的Fortran程序在語法上是不正確的,因此編譯器不受語言標準限制而引發警告或錯誤。

雖然Fortran可以讓您編程函數和子例程,以確保輸出參數具有給定的值。如果對在過程中應賦予值的參數使用intent(out)屬性,則編譯器將檢查是否進行了賦值,如果不是,則會引發錯誤。

大多數編譯器都有一個選項來執行運行時檢查以使用未初始化的變量。例如,英特爾Fortran的標誌爲-check:uninit。如果沒有這個檢查,是的,你的程序將把它在標記爲ifail的內存區域中找到的任何位模式解釋爲一個整數並繼續。

你寫道,你的功能總是失敗ifail == 1。根據您向我們顯示的ifail,在(大概)撥打電話結束前return,無條件設置爲1

從您揭示的代碼看起來,我好像ifail是作爲來自getset的錯誤返回代碼,因此在進入該子例程時未初始化它並不一定是錯誤的。但有一點令人費解,readbh然後在返回之前將它設置爲1

+0

IFAIL是一個變量,它作爲最後一個變量傳遞給遍及此代碼的許多例程,並且遍及整個地方它只是檢查它的值是什麼,在其中一些只是結束程序。在這個例子中,'getset'中有一個用於檢查'IFAIL'是否爲'0'的子句,如果不是,它會將其設置爲1並且不返回任何內容。 – will

+0

'ifort'還有一個標誌,它會自動將所有未初始化(數值)變量初始化爲0(我認爲它是'-zero')。我並不建議讓編譯器初始化變量是一種好的做法,但如果您繼承了糟糕的代碼,則可以使用它。 – SethMMorton

相關問題