使用Fortran中的析构函数释放内存

4

基础: 我正在尝试用Fortran编写优秀的代码,使用构造函数和析构函数。以下是一个非常简单的Test类及其客户端示例:

module test_class_module
implicit none

type :: Test
private
integer, allocatable :: arr(:)
 CONTAINS
    final :: destructor
end type

interface Test
    procedure :: constructor
end interface

 CONTAINS
    function constructor(arr_size) result(this)
        type(Test) :: this
        integer, intent(in) :: arr_size
        write(*,*) 'Constructor works'
        allocate(this % arr(arr_size))
    end function

    subroutine destructor(this)
        type(Test) :: this
        write(*,*) 'Destructor works'
        if (ALLOCATED(this % arr)) deallocate(this % arr)
    end subroutine        
end module

program test_client
    use test_class_module

    type(Test) :: tst
    tst = Test(100)
end

问题: 我使用 valgrind 运行它,并打印出以下结果:

Constructor works
Destructor works
Destructor works
==22229== HEAP SUMMARY:
==22229== in use at exit: 432 bytes in 2 blocks
==22229== total heap usage: 10 allocs, 8 frees, 13,495 bytes allocated

问题:为什么内存仍然被分配?(注:我理解赋值运算符在正确使用类时的必要性,但这对于此问题不足够)感谢任何想法。

2个回答

3

实际上,在程序结束时不应该调用tst的析构函数。根据最新标准,主程序变量隐式地被save了。因此,它只应该在赋值时对右侧的函数结果和tst进行destructor的调用。


“save”属性难道不仅仅是在“end”处防止终结,而是在将“tst”作为内部赋值的左手边进行终结的情况下也会发生吗?这样,两个终结应该会产生吧? - francescalus
1
所以,答案是:“析构函数工作得很好,但不适用于主程序。在这种情况下,内存泄漏是可以接受的。” 是吗? - vovo
1
确切地说,您必须自己调用主程序和模块变量中定义的终结器。 - Vladimir F Героям слава
这是非常奇怪的情况。所以,对于主函数和任何模块变量,我都应该显式地使用“调用析构函数(tst)”的结构。 - vovo
是的,你说得对。如果在终结器中没有其他重要的功能需要完成,那么就让操作系统来清理内存吧。 - Vladimir F Героям слава
显示剩余5条评论

2

为了将来的参考。 如果你在你的测试程序中使用 BLOCK 包装你的三行代码,你将会看到期望的行为。我只修改了你的主程序:

program test_client
    use test_class_module
    write(*,*) '1 program start'
    BLOCK
        type(Test) :: tst
        write(*,*) '2 calling constructor'
        tst = Test(100)
        write(*,*) '3 block ending'
    END BLOCK
    write(*,*) '4 program end'
end

这将产生以下结果:
valgrind bin/SimpleTest
==10031== Memcheck, a memory error detector
...
1 program start
2 calling constructor
Constructor works
3 block ending
Destructor works
4 program end
==10031== 
==10031== HEAP SUMMARY:
==10031==     in use at exit: 0 bytes in 0 blocks
==10031==   total heap usage: 22 allocs, 22 frees, 12,417 bytes allocated
==10031== 
==10031== All heap blocks were freed -- no leaks are possible
==10031== 
==10031== For counts of detected and suppressed errors, rerun with: -v
==10031== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接