background image

  
  而对于长时间运行的服务器守护程序,包括象

Apache 这样的 web 服务器和扩展 php 模

块来说,进程往往被设计为相当长时间一直运行。因为

OS 不能清理内存使用,所以,任何

程序的泄漏

-无论是多么小-都将导致重复操作并最终耗尽所有的系统资源。

  
  现在,我们不妨考虑用户空间内的

stristr()函数;为了使用大小写不敏感的搜索来查找一

个字符串,它实际上创建了两个串的各自的一个小型副本,然后执行一个更传统型的大小
写敏感的搜索来查找相对的偏移量。然而,在定位该字符串的偏移量之后,它不再使用这些
小写版本的字符串。如果它不释放这些副本,那么,每一个使用

stristr()的脚本在每次调用

它时都将泄漏一些内存。最后,

web 服务器进程将拥有所有的系统内存,但却不能够使用它。

  
  你可以理直气壮地说,理想的解决方案就是编写良好、干净的、一致的代码。这当然不错

;

但是,在一个象

PHP 解释器这样的环境中,这种观点仅对了一半。

  
  三、错误处理
  
  为了实现

"跳出"对用户空间脚本及其依赖的扩展函数的一个活动请求,需要使用一种

方法来完全

"跳出"一个活动请求。这是在 Zend 引擎内实现的:在一个请求的开始设置一

"跳出"地址,然后在任何 die()或 exit()调用或在遇到任何关键错误(E_ERROR)时执行一个

longjmp()以跳转到该"跳出"地址。
  
  尽管这个

"跳出"进程能够简化程序执行的流程,但是,在绝大多数情况下,这会意味

着将会跳过资源清除代码部分

(例如 free()调用)并最终导致出现内存漏洞。现在,让我们来

考虑下面这个简化版本的处理函数调用的引擎代码:
  
  以下为引用的内容:
  
  

voidcall_function(constchar*fname,intfname_lenTSRMLS_DC){

  
  

zend_function*fe;

  
  

char*lcase_fname;

  
  

/*PHP 函数名是大小写不敏感的,

  
  

*为了简化在函数表中对它们的定位,

  
  

*所有函数名都隐含地翻译为小写的

  
  

*/

  
  

lcase_fname=estrndup(fname,fname_len);