Может ли аргумент Allocatable Intent(inout) быть необязательным?
У меня проблема при попытке определить подпрограмму, аргумент которой содержит размещаемую, необязательную, намеренную (inout) переменную, показанную ниже. Код компилируется нормально, но выдает ошибку времени выполнения "Ошибка сегментации - недопустимая ссылка на память".
Подпрограмма test_routine.f90
SUBROUTINE test_routine(A,B)
IMPLICIT NONE
REAL,ALLOCATABLE,INTENT(IN) :: A(:,:)
REAL,ALLOCATABLE,OPTIONAL,INTENT(INOUT) :: B(:,:)
B = A
B(:,:) = 1
END SUBROUTINE
Эта подпрограмма упакована в модуль и вызывается в Main.
Модуль test_module.f90
MODULE test_module
IMPLICIT NONE
INTERFACE test_routine
MODULE PROCEDURE test_routine
END INTERFACE
END MODULE test_module
Основной test_main.f90
PROGRAM main
USE test_module
IMPLICIT NONE
REAL,ALLOCATABLE :: A(:,:),B(:,:)
ALLOCATE(A(6,6))
ALLOCATE(B(6,6))
A(:,:) = 0
CALL test_routine(A,B) ! WORKS FINE
CALL test_routine(A) ! DOESN'T WORK!
END PROGRAM main
Затем я попытался назначить другую переменную op_B, чтобы компенсировать B, которая на самом деле не существует, если основная подпрограмма не передает ее. Однако следующий код все еще не работает.
SUBROUTINE test_routine(A,B)
IMPLICIT NONE
REAL,ALLOCATABLE,INTENT(IN) :: A(:,:)
REAL,ALLOCATABLE,OPTIONAL,INTENT(INOUT) :: B(:,:)
REAL,ALLOCATABLE :: op_B(:,:)
IF(.NOT. PRESENT(B)) THEN
ALLOCATE(op_B(SIZE(A,1),SIZE(A,2)))
B = op_B
END IF
B = A
B(:,:) = 1
END SUBROUTINE
Кстати, я также пытался использовать массив фиксированного размера, но все равно не помогает. Интересно, нельзя ли делать такие вещи?
2 ответа
Пустые аргументы могут быть необязательными, размещаемыми и намеренными (inout).
Но вам не разрешено определять или ссылаться на необязательный фиктивный аргумент, запрещая передавать его в PRESENT или ассоциировать с другим необязательным аргументом. Если "B" отсутствует, вы не можете выполнить "B = A".
Основываясь на ответе @lanH, единственный способ, который я сейчас выяснил, - дать псевдоним каждому необязательному фиктивному аргументу. Эта версия работает сейчас.
SUBROUTINE test_routine(A,B)
IMPLICIT NONE
REAL,ALLOCATABLE,INTENT(IN) :: A(:,:)
REAL,ALLOCATABLE,OPTIONAL,INTENT(INOUT) :: B(:,:)
REAL,ALLOCATABLE :: op_B(:,:)
ALLOCATE(op_B(SIZE(A,1),SIZE(A,2)))
op_B = A
op_B(:,:) = 1
IF(PRESENT(B)) THEN
B = op_B
END IF
DEALLOCATE(op_B)
END SUBROUTINE