Позвольте мне рассмотреть функцию, возвращающую массив allocatable
. Должна ли переменная массива, содержащая результат (вне функции) быть выделена перед присваиванием?
Рассмотрим, например, следующую программу
program mem
implicit none
interface
function get_matrix() result(res)
real(kind=kind(0.d0)), allocatable :: res(:,:)
end function get_matrix
end interface
real(kind=kind(0.d0)), allocatable :: w(:,:)
allocate(w(2,2)) ! Is this necessary?
w=get_matrix()
deallocate(w)
end program mem
function get_matrix() result(res)
real(kind=kind(0.d0)), allocatable :: res(:,:)
allocate(res(2,2))
res = 0.d0
res(1, 1) = 1.d0
res(2, 2) = 1.d0
end function get_matrix
Согласно this ,и this , массив res
, выделенный для результата get_matrix
, освобождается, как только выходит из области видимости.
Будет ли присвоение нераспределенной переменной w
в основной программе продлить область действия результата get_matrix
? Другими словами, если я опущу allocate(w(2,2))
в основной программе, получу ли я неопределенное поведение?
Пропуск allocate(w(2,2))
и компиляция с gfortran 9.2.0
и параметрами -Wall -std=f2008
выдает следующие предупреждения
mem.f90:13:0:
13 | w=get_matrix()
|
Warning: ‘w.offset’ is used uninitialized in this function [-Wuninitialized]
mem.f90:13:0: Warning: ‘w.dim[0].lbound’ is used uninitialized in this function [-Wuninitialized]
mem.f90:13:0: Warning: ‘w.dim[0].ubound’ is used uninitialized in this function [-Wuninitialized]
mem.f90:13:0: Warning: ‘w.dim[1].lbound’ is used uninitialized in this function [-Wuninitialized]
mem.f90:13:0: Warning: ‘w.dim[1].ubound’ is used uninitialized in this function [-Wuninitialized]
mem.f90:13:0:
13 | w=get_matrix()
|
Warning: ‘w.dim[0].lbound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
mem.f90:13:0: Warning: ‘w.dim[0].ubound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
mem.f90:13:0: Warning: ‘w.dim[1].lbound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
mem.f90:13:0: Warning: ‘w.dim[1].ubound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
mem.f90:13:0: Warning: ‘w.dim[0].ubound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
mem.f90:13:0: Warning: ‘w.dim[0].lbound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
mem.f90:13:0: Warning: ‘w.dim[1].ubound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
mem.f90:13:0: Warning: ‘w.dim[1].lbound’ may be used uninitialized in this function [-Wmaybe-uninitialized]
Тем не менее, запуск программы с valgrind
, а также компиляция с -fbounds-check
, -fsanitize=address
или -fsanitize=leak
не дает никаких ошибок. Кроме того, инструкция deallocate(w)
в конце не приводит к сбою программы, предполагая, что w
содержит память, выделенную на get_matrix
, и, следовательно, нет необходимости выделять w
в основной программе.
В то же время включение в код allocate(w(2,2))
подавляет предупреждение компилятора. Несмотря на то, что создается впечатление, что одна и та же память выделяется дважды, valgrind
не сообщает об утечке памяти и фактически сообщает об одинаковом использовании памяти.
Как правильно хранить allocatable
массив как результат функции? Нужно ли выделять w
перед сохранением в нем результата get_matrix
?