Символьная переменная отложенной длины, вызывающая утечки памяти, в зависимости от уровня оптимизации - PullRequest
3 голосов
/ 16 июня 2020

Я использую gfortran 8.4 в Ubuntu с символьной переменной отложенной длины, как в следующем примере:

PROGRAM test
   IMPLICIT NONE
   CHARACTER(LEN=:),ALLOCATABLE :: str 
   str = '10'
END PROGRAM test

Если я скомпилирую его с помощью:

gfortran-8 test.f90 -o test -O0

При запуске программа с использованием Valgrind я получаю утечку памяти:

==29119== HEAP SUMMARY:
==29119==     in use at exit: 2 bytes in 1 blocks
==29119==   total heap usage: 22 allocs, 21 frees, 13,522 bytes allocated
==29119== 
==29119== LEAK SUMMARY:
==29119==    definitely lost: 2 bytes in 1 blocks
==29119==    indirectly lost: 0 bytes in 0 blocks
==29119==      possibly lost: 0 bytes in 0 blocks
==29119==    still reachable: 0 bytes in 0 blocks
==29119==         suppressed: 0 bytes in 0 blocks

Однако, компилируя программу с помощью:

gfortran-8 test.f90 -o test -O1

, я получаю в Valgrind:

==29130== HEAP SUMMARY:
==29130==     in use at exit: 0 bytes in 0 blocks
==29130==   total heap usage: 21 allocs, 21 frees, 13,520 bytes allocated
==29130== 
==29130== All heap blocks were freed -- no leaks are possible

Я делаю не понимаю, почему я получаю эту утечку памяти, когда во время компиляции не применяется оптимизация. Заранее спасибо.

Ответы [ 2 ]

6 голосов
/ 26 июня 2020

Все переменные, объявленные в основной программе или как переменные модуля, неявно имеют save. Сохраненные переменные не удаляются автоматически. Стандарт Fortran не требует освобождения массивов в конце программы. В любом случае они будут восстановлены вашей ОС.

Вы можете освободить свои массивы вручную или, если вы sh получите автоматическое c перераспределение, вы можете переместить этот лог c - и выделяемые переменные - в подпрограмму, которая запускается из основной программы. Таким образом, при завершении подпрограммы локальные выделяемые переменные этой подпрограммы будут освобождены. это привносит. Они будут освобождены, когда выполнение блока будет завершено.

Технически происходит то, что код, сгенерированный компилятором для вашей программы, не поддерживает указатели внутри выделяемых дескрипторов до того момента, пока valgrind не захочет их увидеть чтобы они были «все еще достижимы». Это техническая особенность, о которой вам не нужно беспокоиться.

1 голос
/ 16 июня 2020

Возможно, было бы не совсем хорошо позволить ОС выполнять очистку памяти для переменной, у которой есть время жизни до конца программы, но она все еще действительна.

Чтобы избежать этих ложноположительных утечек в valgrind достаточно заключить ваш код в область видимости основной программы, используя конструкцию block.

...