【问题标题】:Can the call stack leak memory if functions don't return?如果函数不返回,调用堆栈会泄漏内存吗?
【发布时间】:2019-08-19 09:12:23
【问题描述】:

我不确定这是如何特定于语言的,但特别是在 PHP 中,如果某些函数永远不会返回,你会在调用堆栈中泄漏内存吗?

例如,假设您有一个带有 redirect()(或 C 中的 goto)语句的长函数,语言或环境如何知道删除堆栈的该帧?有没有一种方法可以确定永远不会返回的堆栈帧?

【问题讨论】:

  • if functions don't return 到底是什么意思?如果不返回,函数会做什么? how does the language or environment know to delete that frame of the stack? Is there a method it uses to determine a stack frame will never be returned to? 这没有任何意义。该函数要么返回,要么不返回,在这种情况下,它仍在运行。没有办法不返回也不运行,除非你exit,在这种情况下整个VM都被破坏了。
  • 例如,PHP 中的 redirect() 语句或 C 中的 goto。这意味着函数不会返回,对吗?据我了解,CPU 会分支到其他一些执行线程。 PHP 环境是否维护自己的调用堆栈?
  • 什么是重定向语句?
  • PHP 中的 redirect() 停止在当前 PHP 脚本上执行,并使用自己的 PHP 脚本定向到另一个页面。到目前为止,我认为 PHP Zend 引擎为每个加载的页面维护一个堆栈。会继续研究

标签: php memory-management memory-leaks stack-trace


【解决方案1】:

如果您的函数在某些情况下不返回任何内容,那么在我看来,这听起来像是一个糟糕的设计问题。不,它不应该仅仅通过不返回任何内容而导致任何内存泄漏。

无论你的函数的返回值最终是否被使用,你都应该有一个返回某些东西的路径(null、false 或任何值)。或者你永远无法返回任何东西......在这种情况下,你的函数将更像是其他编程语言所引用的方法或过程。

如果您正在使用的函数中存在内存泄漏,那么您需要仔细检查函数的代码以查看可能导致泄漏的原因。

【讨论】:

  • 例如,PHP 中的 redirect() 语句或 C 中的 goto 将导致函数不返回。或者,如果函数正在运行的进程发送了一个 SIGKILL,但我想我知道最后一种情况会发生什么。这与任何实际无关,我只是好奇。
  • 关于重定向的要点。例如,某人可能会被重定向到身份验证屏幕。但是 SIGKILL 不是一个很好的例子,因为一个被 kill 的程序无论如何都会被杀死。到那时,没有人会关心内存泄漏。
  • 是的,我了解发送 SIGKILL 时会发生什么。进程从内存中清除,其虚拟地址空间由操作系统回收。不过,我不确定 redirect() 或 gotos。在 PHP 中,我认为到目前为止,zend 引擎为每个页面维护一个调用堆栈。如果您尝试在页面上无限递归,当堆栈达到 256 次调用时,您会收到一个异常。但是您可以转到 255 呼叫,重定向到不同的页面,然后再进行 255 呼叫。所以我想本地页面堆栈只是在加载新页面时被删除,防止整个应用程序泄漏
  • 如果您重定向离开,导致重定向的脚本将一直运行到最后一行代码并且进程退出。除非你有一个无限循环。
【解决方案2】:

Memory leak on the stack回答了这个问题 笔记: 在发布这个问题之前,我确实遇到了这个问题,但直到做更多研究我才明白答案。

Tl;Dr:PHP 为每个页面维护一个堆栈。在 C/C++ 中,“自动持续时间”存储由编译器自动清理,告诉操作系统在程序执行超出这些分配范围时删除自动持续时间分配。

所以我猜编译器可以检测导致函数不返回的执行路径,并且“标记”(?)这些路径移出范围,就像返回被标记为移出范围一样。

https://en.cppreference.com/w/cpp/language/storage_duration

【讨论】:

  • 我应该澄清一下:我对一般编译器或 PHP zend 引擎的工作方式只有最模糊的了解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2013-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
相关资源
最近更新 更多