根据优化级别导致内存泄漏的延迟长度字符变量
Deferred-length character variable causing memory leaks depending on the optimization level
我在 Ubuntu 中使用带有延迟长度字符变量的 gfortran 8.4,如下例所示:
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
我不明白为什么在编译时没有应用优化时会发生内存泄漏。提前致谢。
让 OS 为生命周期到程序结束的变量执行内存清理可能不是很好,但它仍然有效。
为了避免 valgrind 中的这些误报泄漏,使用 block
构造将您的代码包含在主程序中包含的范围内就足够了。
在主程序中或作为模块变量声明的所有变量都是隐式的save
。保存的变量不会自动释放。 Fortran 标准不强制在程序结束时释放数组。无论如何,它们都会被您的 OS 回收。
您可以手动解除分配数组,或者如果您希望获得自动重新分配,您可以将该逻辑和可分配变量移动到从主程序输入的子例程中。这样,该子程序的局部可分配变量将在子程序完成时被释放。
或者,您也可以使用 block
和 end block
创建一个块,并在块内声明可分配变量及其带来的所有内容。当块执行完成时,它们将被释放。
从技术上讲,编译器为您的程序生成的代码不会在可分配描述符内维护指针,直到 valgrind 希望看到它们“仍然可访问”时。这是您不必担心的技术问题。
我在 Ubuntu 中使用带有延迟长度字符变量的 gfortran 8.4,如下例所示:
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
我不明白为什么在编译时没有应用优化时会发生内存泄漏。提前致谢。
让 OS 为生命周期到程序结束的变量执行内存清理可能不是很好,但它仍然有效。
为了避免 valgrind 中的这些误报泄漏,使用 block
构造将您的代码包含在主程序中包含的范围内就足够了。
在主程序中或作为模块变量声明的所有变量都是隐式的save
。保存的变量不会自动释放。 Fortran 标准不强制在程序结束时释放数组。无论如何,它们都会被您的 OS 回收。
您可以手动解除分配数组,或者如果您希望获得自动重新分配,您可以将该逻辑和可分配变量移动到从主程序输入的子例程中。这样,该子程序的局部可分配变量将在子程序完成时被释放。
或者,您也可以使用 block
和 end block
创建一个块,并在块内声明可分配变量及其带来的所有内容。当块执行完成时,它们将被释放。
从技术上讲,编译器为您的程序生成的代码不会在可分配描述符内维护指针,直到 valgrind 希望看到它们“仍然可访问”时。这是您不必担心的技术问题。