根据优化级别导致内存泄漏的延迟长度字符变量

Emi*_*lio 3 fortran memory-leaks gfortran

我在 Ubuntu 中使用带有延迟长度字符变量的 gfortran 8.4,如下例所示:

PROGRAM test
   IMPLICIT NONE
   CHARACTER(LEN=:),ALLOCATABLE :: str 
   str = '10'
END PROGRAM test
Run Code Online (Sandbox Code Playgroud)

如果我使用以下方法编译它:

gfortran-8 test.f90 -o test -O0
Run Code Online (Sandbox Code Playgroud)

使用 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
Run Code Online (Sandbox Code Playgroud)

但是,使用以下命令编译程序:

gfortran-8 test.f90 -o test -O1
Run Code Online (Sandbox Code Playgroud)

我进入 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
Run Code Online (Sandbox Code Playgroud)

我不明白为什么在编译时没有应用优化时会出现这种内存泄漏。提前致谢。

Vla*_*r F 7

在主程序中声明或作为模块变量声明的所有变量都是隐式的save。保存的变量不会自动解除分配。Fortran 标准不强制要求在程序结束时重新分配数组。无论如何,它们将被您的操作系统回收。

您可以手动取消分配数组,或者如果您希望自动重新分配,您可以将该逻辑 - 以及可分配的变量 - 移动到从主程序输入的子例程中。这样子程序完成时,该子程序的局部可分配变量将被释放。

或者,您也可以使用block和创建一个块,end block并使用它带来的所有变量在块内声明可分配的变量。当块的执行完成时,它们将被释放。

从技术上讲,编译器为您的程序生成的代码不会维护可分配描述符内的指针,直到 valgrind 希望看到它们“仍然可以访问”。这是您不必担心的技术问题。