2013-05-08 188 views
6

目前我正在試圖用Fortran編寫一個小子程序釋放了所有的變量分配內存時,我的程序涉及到一個錯誤,即未能加載文件或不存在的必要文件。在這一點上,執行必須終止,但並非所有的可分配都必須分配(這取決於錯誤出現在代碼的哪個位置),所以我無法進行清除所有分配。的Fortran DEALLOCATE

我目前的做法是:

SUBROUTINE Cleanup(A) 

    REAL(8), ALLOCATABLE, DIMENSION(:) :: A 

    IF (ALLOCATED(A)) THEN 
     DEALLOCATE(A) 
    END IF 

END SUBROUTINE 

,並呼籲 「清理」 爲每一個分配。這個問題是,並不是我所有的變量都是維度-1。其中一些我有三個維度。

我第一次想過寫3個不同的子程序爲不同的尺寸和使用重載,但這並不似乎是很優雅。

然後它來到我的腦海裏,也許我可以傳遞一個指針,而不是實際工作參數A,但我GOOGLE了,似乎你不能解除分配目標變量槽的指針。

有關如何做到這一點適當的任何想法?

謝謝。

+4

當執行結束時,代碼使用的所有資源都會自動釋放,因此您不必擔心明確釋放它們。 – 2013-05-08 08:54:09

+1

我知道Fortran會自動釋放內存,但在這種情況下,我正在寫一個從Labview調用的dll,所以這是誰在管理內存。當dll發生錯誤時,Labview突然停止,如果我嘗試重新執行,它將顯示消息:「Array已分配」並關閉。這意味着內存不能正確釋放。 – derkomai 2013-05-08 09:02:59

+1

注意:'real(8)'不保證是8個字節。可移植的方式是使用ISO_FORTRAN_ENV,對64位使用「real(real64)」。 – 2013-05-08 13:35:03

回答

7

我的這種方法可以使用以下組合:

  • 作爲Fortran 95的,當一個程序完成自動釋放所有分配的本地未保存的可分配變量。這是否適用取決於您的DLL的調用方式,因此您是否可以實際構造所有可分配對象都是未保存的本地對象。從Fortran 2003(或Fortran 95 +可分配的TR--該語言級別在維護的Fortran編譯器中得到廣泛支持)開始,可分配的實際參數傳遞給INTENT(OUT)可分配的僞參數將在過程開始執行之前自動解除分配。問題中的Cleanup例程只需將僞參數的聲明添加爲INTENT(OUT),然後就不需要IF測試或DEALLOCATE。你仍然需要爲你需要清理的每種類型和等級編寫例程。

  • 到傳遞給一個INTENT(OUT)派生類型變量僞參數的先前,分配組件類似的將被自動解除分配。因此,您可能能夠將所有可分配變量作爲派生類型對象中的組件收集在一起。然後清理只需將該對象傳遞給具有INTENT(OUT)虛擬的過程。此處的INTENT(OUT)還會將具有默認初始化的組件重置回其「默認」值。也許還有其他清理工作需要您手動完成(關閉文件等)。

  • 的另一種方法,再次使用派生類型與所有的變量成分,是使派生類對象本身分配。當你需要清理時,只需釋放一個對象 - 它的組件將被自動釋放。 Fortran 2003允許通過此類事件觸發最終過程,如果此時還需要執行其他清理操作。

派生類型的方法也可以很容易地有什麼你DLL支持在一個時間(你只是派生類型的多個對象)獨立活動的多個實例。,鑑於派生類型方法的

實例:

TYPE MyType 
    REAL, ALLOCATABLE :: variable_one(:) 
    INTEGER, ALLOCATABLE :: variable_two(:) 
    ... 
END TYPE MyType 

INTENT(OUT)虛設

TYPE(MyType) :: object 
ALLOCATE(object%variable_one(xxx)) 
ALLOCATE(object%variable_two(yyy)) 
... 
IF (things_have_gone_wrong) CALL Cleanup(object) 
... 
SUBROUTINE Cleanup(arg) 
    TYPE(MyType), INTENT(OUT) :: arg 
END SUBROUTINE Cleanup 

ALLOCATABLE對象。

TYPE(MyType), ALLOCATABLE :: object 
ALLOCATE(object) 
ALLOCATE(object%variable_one(...)) 
ALLOCATE(object%variable_two(...)) 

... 
IF (things_have_gone_wrong) DEALLOCATE(object) 
+1

非常好,非常感謝! – derkomai 2013-05-08 11:49:52

+2

另一種方式我已經找到了解決這個問題是使用預處理器宏: 的#define清理(A)IF(撥(A))DEALLOCATE(A) 調用時,清理做這項工作。 – derkomai 2013-05-08 11:56:53