Переполнение стека в Fortran 90

Я написал довольно большую программу на Fortran 90. В ней есть долгое время работал красиво, но сегодня я попытался поднять его на ступеньку выше и увеличить размер проблемы (это исследовательский нестандартный FE-решатель, если это кому-то поможет ...) Теперь я получаю сообщение "переполнение стека" " сообщение об ошибке и, естественно, программа завершается, не дав мне ничего полезного для работы.

Программа начинается с настройки всех соответствующих массивов и матриц, а после этого она выводит несколько строк статистики об этом в файл журнала . Даже с моей новой, более крупной проблемой, это работает нормально (хотя и немного медленно), но затем это терпит неудачу, поскольку начинается "обработка чисел".

Что меня смущает, так это то, что все на тот момент уже выделено (и это сработало без ошибок). Я не совсем уверен, что это за стек (Википедия и несколько шагов здесь мало что сделали, так как у меня есть только довольно базовые знания о "закулисной" работе компьютера).

Предположим, что я, например, имеют некоторые массивы, инициализированные как:

INTEGER,DIMENSION(64) :: IA
REAL(8),DIMENSION(:,:),ALLOCATABLE :: AA, BB

, которые после некоторых процедур инициализации (т.е. чтение ввода из файла и т. д.) распределяются как (я храню некоторые целые числа размера для облегчения передачи подпрограмм фиксированного размера в IA):

ALLOCATE( AA(N1,N2) , BB(N1,N2) )
IA(1) = N1
IA(2) = N2

Это в основном то, что происходит в начальной части, и пока все хорошо. Но когда я затем вызываю подпрограмму

CALL ROUTINE_ONE(AA,BB,IA)

, она выглядит так (ничего особенного):

SUBROUTINE ROUTINE_ONE(AA,BB,IA)
IMPLICIT NONE
INTEGER,DIMENSION(64) :: IA
REAL(8),DIMENSION(IA(1),IA(2)) :: AA, BB
...
do lots of other stuff
...
END SUBROUTINE ROUTINE_ONE

Теперь я получаю сообщение об ошибке! Вывод на экран говорит:

forrtl: severe (170): Program Exception - stack overflow

Однако, когда я запускаю программу с отладчиком, она прерывает строку 419 в файле с именем winsig.c (не мой файл, но, вероятно, часть компилятора? ). Кажется, это часть подпрограммы под названием sigreterror: , и это случай по умолчанию, который был вызван, возвращая текст Недействительный сигнал или ошибку . К нему прилагается строка комментария, в которой странным образом говорится, что / * никогда не должно происходить, но компилятор не может сказать * / ... ?

Итак, я думаю, мой вопрос: почему это происходит и что происходит на самом деле? Я думал, что пока я могу выделить всю необходимую память, со мной все будет в порядке? Создает ли вызов подпрограммы копии аргументов или просто указатели на них? Если ответ - копии, то я вижу, в чем может быть проблема, и если да: есть ли идеи, как ее обойти?

Проблема, которую я пытаюсь решить, большая, но ни в коем случае не безумная. Стандартные решатели FE могут справиться с более серьезными проблемами, чем моя нынешняя. Я запускаю программу на Dell PowerEdge 1850, а операционная система - Microsoft Server 2008 R2 Enterprise. Согласно systeminfo в приглашении cmd , у меня 8 ГБ физической памяти и почти 16 ГБ виртуальной. Насколько я понимаю, общая сумма всех моих массивов и матриц не должна составлять более 100 МБ - около 5. 5M integer (4) и 2,5M real (8) (что, по моему мнению, должно быть всего около 44MB, но давайте будем честны и добавим еще 50MB на накладные расходы).

Я использую компилятор Intel Fortran, интегрированный с Microsoft Visual Studio 2008.


Добавление некоторого фактического исходного кода, чтобы немного прояснить

! Update continuum state
CALL UpdateContinuumState(iTask,iArray,posc,dof,dof_k,nodedof,elm,&
                    bmtrx,detjac,w,mtrlprops,demtrx,dt,stress,strain,effstrain,&
                    effstress,aa,fi,errmsg)

, является фактическим вызовом процедуры. Большие массивы - это posc , bmtrx и aa - все остальные как минимум на порядок меньше (если не больше). posc is INTEGER (4) и bmtrx и aa is REAL (8)

SUBROUTINE UpdateContinuumState(iTask,iArray,posc,dof,dof_k,nodedof,elm,bmtrx,&
                    detjac,w,mtrlprops,demtrx,dt,stress,strain,effstrain,&
                    effstress,aa,fi,errmsg)

    IMPLICIT NONE

    !I/O
    INTEGER(4) :: iTask, errmsg
    INTEGER(4) :: iArray(64)
    INTEGER(4),DIMENSION(iArray(15),iArray(15),iArray(5)) :: posc
    INTEGER(4),DIMENSION(iArray(22),iArray(21)+1) :: nodedof
    INTEGER(4),DIMENSION(iArray(29),iArray(3)+2) :: elm
    REAL(8),DIMENSION(iArray(14)) :: dof, dof_k
    REAL(8),DIMENSION(iArray(12)*iArray(17),iArray(15)*iArray(5)) :: bmtrx
    REAL(8),DIMENSION(iArray(5)*iArray(17)) :: detjac
    REAL(8),DIMENSION(iArray(17)) :: w
    REAL(8),DIMENSION(iArray(23),iArray(19)) :: mtrlprops
    REAL(8),DIMENSION(iArray(8),iArray(8),iArray(23)) :: demtrx
    REAL(8) :: dt
    REAL(8),DIMENSION(2,iArray(12)*iArray(17)*iArray(5)) :: stress
    REAL(8),DIMENSION(iArray(12)*iArray(17)*iArray(5)) :: strain
    REAL(8),DIMENSION(2,iArray(17)*iArray(5)) :: effstrain, effstress
    REAL(8),DIMENSION(iArray(25)) :: aa
    REAL(8),DIMENSION(iArray(14)) :: fi 

    !Locals
    INTEGER(4) :: i, e, mtrl, i1, i2, j1, j2, k1, k2, dim, planetype, elmnodes, &
        Nec, elmpnodes, Ndisp, Nstr, Ncomp, Ngpt, Ndofelm
    INTEGER(4),DIMENSION(iArray(15)) :: doflist
    REAL(8),DIMENSION(iArray(12)*iArray(17),iArray(15)) :: belm
    REAL(8),DIMENSION(iArray(17)) :: jelm
    REAL(8),DIMENSION(iArray(12)*iArray(17)*iArray(5)) :: dstrain
    REAL(8),DIMENSION(iArray(12)*iArray(17)) :: s
    REAL(8),DIMENSION(iArray(17)) :: ep, es, dep
    REAL(8),DIMENSION(iArray(15),iArray(15)) :: kelm
    REAL(8),DIMENSION(iArray(15)) :: felm

    dim       = iArray(1)
...

И это не удается до последняя строка выше.

8
задан Vladimir F 4 April 2017 в 18:40
поделиться