2012-07-19 70 views
2

我很困惑Fortran如何處理這種情況,如果引用數組元素的索引實際上超出了它所設想的範圍。數組的索引超出範圍

下面是一個簡單的代碼來說明問題:

PROGRAM test_matrix_out 

USE mod_writearray 

IMPLICIT NONE 
INTEGER :: i,j,m,n 
REAL :: k 
REAL, Dimension(:,:),ALLOCATABLE :: A 

m = 3 
n = 4 
ALLOCATE(A(m,n)) 

k = 1 

DO i=1,m 
    DO j=1,n 
     A(i,j)=k 
     k=k+1 
    ENDDO 
ENDDO 

CALL writearray(A) 
WRITE(*,*) 
WRITE(*,*) A(1,:) 
WRITE(*,*) 
WRITE(*,*) A(2,:) 
WRITE(*,*) 
WRITE(*,*) A(0,:) 
WRITE(*,*) 
WRITE(*,*) A(4,:) 
WRITE(*,*) 
WRITE(*,*) A(5,:) 
WRITE(*,*) 
WRITE(*,*) A(100,:) 
WRITE(*,*) 
WRITE(*,*) A(:,1) 
WRITE(*,*) 
WRITE(*,*) A(:,2) 
WRITE(*,*) 
WRITE(*,*) A(:,0) 
WRITE(*,*) 
WRITE(*,*) A(:,4) 
WRITE(*,*) 
WRITE(*,*) A(:,5) 
WRITE(*,*) 
WRITE(*,*) A(:,100) 


DEALLOCATE(A) 

END PROGRAM test_matrix_out 

它給了我以下結果:

1.000000  2.000000  3.000000  4.000000 

    5.000000  6.000000  7.000000  8.000000 

    0.0000000E+00 9.000000  10.00000  11.00000 

    2.000000  3.000000  4.000000  0.0000000E+00 

    6.000000  7.000000  8.000000  0.0000000E+00 

    0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 

    1.000000  5.000000  9.000000 

    2.000000  6.000000  10.00000 

-1.0097448E-28 8.9776148E-39 0.0000000E+00 

    4.000000  8.000000  12.00000 

    0.0000000E+00 0.0000000E+00 0.0000000E+00 

-3.3631163E-44 1.4293244E-43 0.0000000E+00 

爲什麼會出現這種情況?

回答

6

當您編寫A(i,j)時,編譯器會計算該內存位置的地址。例如參見http://en.wikipedia.org/wiki/Array_data_structure#Multidimensional_arrays。根據語言的規則,編譯器通常不會確定這是否是合法地址。使用超過維度的索引是非法的。程序員有責任不這樣做。 Fortran的一個優點是能夠爲這個錯誤添加運行時檢查。傳統的知識是運行時間下標檢查很昂貴,但是當我測試時,我經常發現運行時成本可以忽略不計,有時會將其保留在生產版本的程序中。

如果你正在讀內存索引錯誤的可能後果將獲得一個錯誤的值,除非存儲位置是如此的遙遠,它是屬於程序,這將創建一個故障記憶之外。如果您正在寫入內存,則會損壞陣列中其他位置的內存,屬於某個其他變量,或者屬於程序的內部數據結構。有關索引錯誤導致程序運行時出現問題的示例問題,請參見what kind of problems can lack of deallocation cause?

5

您所看到的是您用來編譯程序的編譯器不檢查數組是否在運行時出界。所以,取決於編譯器和機器,什麼都可以。有時,可能會引用內存中未明確分配的數組元素,這就是您的示例中所發生的情況。在這種情況下,超出邊界的元素的值就是程序運行時在該內存地址處的任何值。如果請求的存儲器地址不存在或無法訪問,則程序將因分段故障而失敗。

我只是在尋找在目前Fortran標準的草案,我找不到任何關於是否訪問數組元素越界是一個定義的行爲的任何聲明。爲了避免這些問題,請使用-C(檢查邊界)標誌編譯您的程序。如果可能的話,程序會讓你知道哪個數組的哪個元素超出了界限。在開發過程中使用-C,但在生產中不使用,因爲它極大地降低了代碼的速度。另外,爲了將來的參考,在提出這類問題時(例如爲什麼我的程序輸出這個問題?),最好包括正在使用的編譯器(帶有版本號)和目標體系結構的信息。

+2

標準不允許訪問數組元素超出範圍,但不需要檢查ftp://ftp.nag.co.uk/sc22wg5/N1901-N1950/N1915.pdf(拉格朗日的讀數也很好) – 2012-07-19 07:53:17

+0

非常感謝你們!非常有用的評論! – 2012-07-19 12:14:53

+0

@VladimirF謝謝!很高興知道。 – milancurcic 2012-07-19 14:28:28