【问题标题】:Memory leak by returning allocated strings通过返回分配的字符串导致内存泄漏
【发布时间】:2019-03-08 16:41:39
【问题描述】:

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

  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) 的理解正确,我仍然可以相信它已被释放。

【问题讨论】:

  • 在本例中使用:write 语句完成后不再需要该值。 (也许甚至在创建了一个临时的连接之后。)但是对于循环的每次迭代,我们都有不同的函数结果。

标签: string function memory-leaks fortran


【解决方案1】:

这个问题是this other one的一个具体案例,但具体可以让我们更准确。您应该阅读那里的答案以了解更多一般细节。

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

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

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

因此,内存可能会“泄漏”一小段时间,但应该会很快地进行回收。许多级别的函数评估可能会导致问题 - 但在此之前你可能已经得到了令人讨厌的代码。

【讨论】:

    【解决方案2】:

    如果您的代码从未解除分配结果,或者可能更相关的是,如果它从未超出范围,那么您只有相信结果永远不会被解除分配是正确的。但是只有在丢失对已分配内存的最后一个引用时才会发生内存泄漏,而且在现代 Fortran 中实际上很难做到这一点,尤其是对于可分配的变量,但使用指针稍微容易一些。

    如果变量是在另一个例程的范围内分配的,它将在例程完成时被操作系统回收(因为这是 Fortran 标准所说的必须发生的事情)。如果它在程序范围内并且从未被释放,则它不是内存泄漏。

    【讨论】:

      猜你喜欢
      • 2011-06-12
      • 2011-11-09
      • 1970-01-01
      • 2019-08-12
      • 2021-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-05
      相关资源
      最近更新 更多