通过返回分配的字符串导致内存泄漏

时间:2019-03-08 16:41:39

标签: string function memory-leaks fortran

this问题中,建议在Fortran中返回可变长度字符串的解决方案:

  function itoa(i) result(res)
    character(:),allocatable :: res
    integer,intent(in) :: i
    character(range(i)+2) :: tmp
    write(tmp,'(i0)') i
    res = trim(tmp)
  end function

我的理解正确吗,这个函数的结果永远不会被释放?因此,对于大量和大量的呼叫,您可能会遇到内存泄漏。

所以我的意思是我不分配函数结果,而是像在“原地”中那样使用它的情况

do i = 1, n
    write(*, *) "tmp_"//itoa(i)
end do

我显然没有提及可以调用deallocate的结果,并且在循环时,绝对不会超出范围。

如果我对您(@Francescalus)的理解正确,我仍然可以依靠它已被释放的事实。

2 个答案:

答案 0 :(得分:2)

这个问题是this other one的一个特例,但具体而言,它使我们更精确。您应该在那儿阅读答案,以获取更多常规信息。

在正确的实现中不会出现内存泄漏。 Fortran标准明确地解决了这些结果。例如,在Fortran 2008中,注释12.41说:

  

函数结果与函数子程序本地的任何其他实体(变量或过程指针)相似。它的存在在启动功能执行时开始,在功能执行终止时结束。但是,由于此实体的最终值随后会在调用该函数的表达式的评估中使用,因此实现可能希望推迟释放该实体所占用的存储,直到将其值用于表达式评估之后。

当可分配函数结果的存在结束时,将其释放。所有可分配的结果都会发生这种情况,而不仅仅是延迟长度的字符串。

因此,内存可能会“泄漏”一小会儿,但是应该很快就可以回收。函数评估的许多级别可能会导致问题-但是在那之前很长一段时间,您可能就已经获得了讨厌的代码。

答案 1 :(得分:1)

您只有权利相信,如果您的代码从未取消分配结果,或者如果它从未超出范围,则可能更相关,因此永远不会取消分配结果。但是,只有当您丢失对分配的内存的最后一个引用时,才会发生内存泄漏,而在现代Fortran中,这样做实际上是非常困难的,尤其是对于可分配变量而言,但是使用指针稍微容易一些。

如果变量在另一个例程的范围内分配,则例程结束时,操作系统(“ cos,这是Fortran标准所说的必须发生的)将获得收益。而且,如果它在程序范围内并且从未被释放,则不是内存泄漏。