У меня есть программа на Фортране, структура которой приведена ниже. Эта программа вылетала из-за ошибки «Ошибка сегментации», поэтому я много копался в первопричине.
Оказывается, в подпрограмме SUB1, когда переменная счетчика цикла DO I достигает значения 187606, значение Z(608673), которое изначально было прочитано как 28,29 из внешнего файла, каким-то необъяснимым образом меняется на 3.9809702045652999E-309, хотя не было вычислений, которые изменили бы значения любого из массивов X, Y или Z после чтения из внешнего файла.
Я подозреваю, что многие другие значения элементов массива также устанавливаются программой в произвольные числа в середине выполнения (вероятно, около нуля) - хотя это невозможно явно проверить, учитывая большой размер массива - но по сути это что вызывает сбой программы (эти значения используются в других частях программы).
Итак, главный вопрос: почему значения элементов массива произвольно сбрасываются программой, хотя эти массивы СОХРАНЯЮТСЯ в ПЕРЕМЕННЫХ МОДУЛЯ, а этот модуль ИСПОЛЬЗУЕТСЯ всеми соответствующими подпрограммами? Разве оператор SAVE не предназначен для сохранения значений массивов?
Примечание. Я пытался запустить этот код на [a] ноутбуке Dell с Ubuntu Linux с 16 ГБ ОЗУ (никаких других программ, требующих памяти), и [b] на ноутбуке с Windows с 16 ГБ ОЗУ. На обеих этих машинах я использовал компилятор gfortran, и возникла та же проблема. При небольших значениях N код работает нормально — проблема возникает только с очень большими массивами.
Файл vars.f90
MODULE VARIABLES
......
......
INTEGER :: N
REAL(8), DIMENSION(:), ALLOCATABLE :: X,Y,Z
SAVE N
SAVE X,Y,Z
.....
.....
... (several other variable declarations) ....
END MODULE VARIABLES
Распределить файл.f90
MODULE ALLOCATE_ARRAYS
CONTAINS
SUBROUTINE ALLOC_ARR
USE VARIABLES
USE DEALLOCATE_ARRAYS
.....
ALLOCATE(X(N),Y(N),Z(N), STAT=IALLOC)
IF (IALLOC /= 0) THEN
WRITE(6,*)' ERROR while allocating arrays X Y Z'
CALL DEALLOC_ARRAYS
STOP
ENDIF
.....
END SUBROUTINE ALLOC_ARR
END MODULE ALLOCATE_ARRAYS
Файл освободить.f90
MODULE DEALLOCATE_ARRAYS
CONTAINS
SUBROUTINE DEALLOC_ARR
USE VARIABLES
.....
IF (ALLOCATED(X)) DEALLOCATE(X)
IF (ALLOCATED(Y)) DEALLOCATE(Y)
IF (ALLOCATED(X)) DEALLOCATE(X)
...
END SUBROUTINE DEALLOC_ARR
END MODULE DEALLOCATE_ARRAYS
Файл main.f90
PROGRAM PROG1
USE VARIABLES
USE ALLOCATE_ARRAYS
USE DEALLOCATE_ARRAYS
.....
N = 18666800 ![in practice this is read from an external input file]
CALL ALLOC_ARR !Allocate X,Y,Z each to be of length N
!Read all values of X(1:N), Y(1:N) and Z(1:N) from an external file] ...
OPEN(11,FILE=datafile.txt,STATUS='OLD')
DO I = 1,N
READ(11,*,IOSTAT=ISTAT) X,Y,Z
IF ( ISTAT /= 0 ) THEN
WRITE(6,*)' *** SERIOUS WARNING ***'
WRITE(6,*)' Something went wrong while trying to read numbers X Y Z at I = ',I
READ(5,*)
ENDIF
ENDDO
CLOSE(11)
CALL SUB1
.....
CALL DEALLOC_ARRAYS
END PROGRAM PROG1
SUBROUTINE SUB1
USE VARIABLES
USE ALLOCATE_ARRAYS
USE DEALLOCATE_ARRAYS
.....
DO I = 1,N
write(6,*)' X(608673) Y(608673) Z(608673) = ',X(608673),Y(608673),Z(608673) ![this statement only inserted for tracing the bug]
CALL SUB2(I,X(I),Y(I),Z(I))
ENDDO
END SUBROUTINE SUB1
SUBROUTINE SUB2(IPASS,XPASS,YPASS,ZPASS)
USE VARIABLES
USE ALLOCATE_ARRAYS
USE DEALLOCATE_ARRAYS
[carry out some calculations that use the values of IPASS, XPASS, YPASS, ZPASS, but never change their values]
END SUBROUTINE SUB2
Файл datafile.txt (небольшой образец):
.....
.....
10879.544935 1200.249974 28.290163
10914.193168 205.374638 236.847393
23872.837623 3634.498293 23721.923293
.....
.....
ulimit -s unlimited
для обхода ограничений на размер стека (в Linux). Кроме того, запуск вашей программы с помощью Valgrind может указать вам на что-то. - person jacob   schedule 11.09.2019