<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>风雪之隅 &#187; PHP</title>
	<atom:link href="http://www.laruence.com/tag/php/feed" rel="self" type="application/rss+xml" />
	<link>http://www.laruence.com</link>
	<description>PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 - 左手代码 右手诗</description>
	<lastBuildDate>Thu, 02 Feb 2012 03:59:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>我们什么时候应该使用异常?</title>
		<link>http://www.laruence.com/2012/02/02/2515.html</link>
		<comments>http://www.laruence.com/2012/02/02/2515.html#comments</comments>
		<pubDate>Thu, 02 Feb 2012 03:36:06 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[exception]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[status code]]></category>
		<category><![CDATA[异常]]></category>
		<category><![CDATA[状态码]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2515</guid>
		<description><![CDATA[先说个题外话: 在公司做了俩件事, 是我觉得很有意义的, 第一就是成立了一个PHP邮件组, 第二就是成立了一个Hi群. 目前俩者都有超过500 phpers在里面.  我一直认为, 构建一个交流平台, 让同学们能顺畅, 简单的沟通, 是营造积极的技术学习氛围的基础和前提. 让每个人的问题不会成为别人的问题, 则是最直接的利益.
 
   昨天, 有同事在邮件组提了个问题:
<blockquote>
PHP应该什么时候使用 Exception ？ 它的性能如何？
</blockquote>

  这个问题也算是一个久经争论的经典问题了.  我谈谈我的个人看法.
]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2012/02/02/2515.html"  title="Permanet Link to 我们什么时候应该使用异常?" >http://www.laruence.com/2012/02/02/2515.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   先说个题外话: 在公司做了俩件事, 是我觉得很有意义的, 第一就是成立了一个PHP邮件组, 第二就是成立了一个Hi群. 目前俩者都有超过500 phpers在里面.  我一直认为, 构建一个交流平台, 让同学们能顺畅, 简单的沟通, 是营造积极的技术学习氛围的基础和前提. 让每个人的问题不会成为别人的问题, 则是最直接的利益.</p>
<p>   昨天, 有同事在邮件组提了个问题:</p>
<blockquote><p>
PHP应该什么时候使用 Exception ？ 它的性能如何？
</p></blockquote>
<p>  这个问题也算是一个久经争论的经典问题了.  我谈谈我的个人看法.</p>
<p>  异常与之对应的错误码(或者状态码),  到底各自有什么优点, 缺点, 我们应该怎么使用呢? </p>
<h3>错误码</h3>
<p>  首先来说, 异常机制是在错误码机制之后才出现的, 那么根据进化论, 异常自然是避免了错误码机制的一些不足. 这些不足包括.</p>
<h4>1. 错误信息不丰富</h4>
<p>   函数, 只能有一个返回值(当然, Lua可以返回多个, 但其实也相当于在PHP中返回一个数组),  我们见过最多的函数说明就是: 成功时候返回***, 错误的时候返回FALSE, 然而一个函数出错我原因可能有多种, 出错的种类更有多种. 一个简单的FALSE, 并不能把具体的错误信息告诉调用者. </p>
<p>   于是, 我们也就见过一些, 这样的函数说明: 如果返回值大于0, 则表示成功的状态码,  如果返回值小于0, 则表示出错的状态码. </p>
<p>   然而, 这个要求函数是返回整形(或者数字),  对于一些其他函数, 我们并不能通过0, >0,  <0来判别, 并且, 即使通过这样的方式, 我们还需要用返回的错误码和一些预定义宏(或者调用类似strerror())来获取具体的, 可读的错误信息.</p>
<p>   于是, 就有一些函数使用全局的错误码, 和错误信息, 来保存具体的错误信息, 这个时候我们就看到这样的函数描述: 成功返回***, 出错的时候返回FALSE, 错误代码保存在全局变量$errno中(至少大多数Linux库函数是这样描述的, 呵呵).</p>
<p>   Okey, 这样的方式确实可以工作, 但是, 是不是觉得, 很丑陋呢?</p>
<h4>2. 加入错误状态码可能需要改变函数签名</h4>
<p>   假设, 你编写了一个函数,  这个函数很简单, 很简单, 你认为他绝对不会出错, 于是你申明为(用C语言为例, PHP没有返回类型提示):</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
void dummy() {
}
</pre>
<p>  但是后来你慢慢修改了这个函数, 给了它更多的功能, 此时这个函数可能会失败了. 而你现在根本无法为这个函数, 加入错误返回码了.  </p>
<p>  也许有人说PHP没有返回值类型限制一说, 但是想想PHP的构造函数, 构造函数是没有返回值的, 当发生错误的时候, 如果你不使用异常, 我想你只能选择die, 或者使用2中的方法来错误继续执行了.</p>
<p>  另外, 在一个良好的软件系统中, 返回类型其实也是约定俗成的,  当所有的使用的函数的地方, 都没有检查返回值的时候, 你还是无法为这个函数加入错误返回码.</p>
<h4>3. 错误状态码可能会被忽略</h4>
<p>   当你的一个函数, 出错了, 返回了错误状态码, 而调用方并没有检测这个返回值,  会发生什么情况呢?  -_#.   令一方面,  处处检测返回状态码, 会造成代码非常的,,ugly:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
  if (!call1()) {
      die();
  }

  if (call2() != SUCCESS) {
     die();
  }

  if (call3() &lt; 0) {
      $msg = error_get_last();
      die($msg[&quot;message&quot;]);
  }
</pre>
<h3>异常机制</h3>
<p>  那么现在我们来看看异常机制, 如果我们采用异常机制,  上面的代码可以写作:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
try {
   call1();
   call2();
   call3();
} catch (Exception $e) {
   die($e-&gt;getMessage());
}
</pre>
<p>   更方便的, 如果你的代码只是中间层, 你的调用方会负责处理错误的话, 你甚至可以简单的写作:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
function myFunc() {
   call1();
   call2();
   call3();
}
</pre>
<p>   而一个异常对象, 可以包含更丰富的错误信息, 比如错误信息, 错误码, 错误的行数, 文件, 甚至出错上下文, 等等, 避免的&#8221;1.错误信息不丰富&#8221;的不足.</p>
<p>   我们也可以为一个返回void类型的函数增加异常,  而不改变他的函数签名, 也就不会有上面说的&#8221;2.加入错误状态码可能需要改变函数签名&#8221;.  对于PHP来说, 如果我们新加入的错误没有被捕捉, 也不用担心, 会明显的出错的. 也就不会发生上面所说的&#8221;3. 错误状态码可能会被忽略&#8221;的情况.</p>
<p>   然而, 也有一些反对使用异常的声音:</p>
<h4> 1. 性能</h4>
<p>    正如文章开头提问中的: &#8220;它的性能如何？&#8221;,  异常机制确实要比返回状态码的方式昂贵一些, 对于C++来说, 在异常发生的时候, 还要发生堆栈解退(对于PHP来说, 没有这个逻辑, 具体的大家可以参看我之间写的一篇文章:<a href="http://www.laruence.com/2010/08/03/1697.html" > 深入理解PHP原理之异常机制</a>). </p>
<p>    性能和方便, 往往是一个矛盾体,  我只能说, 你需要权衡,  如果你写的是一个小的模块, 并且它的生命期可能很短, 也不需要什么特殊的设计模式, 那我觉得你可以不用异常.</p>
<p>    而如果你在为一个庞大的软件做开发, 我想你更应该看重的, 应该是, 它的可扩展性, 可维护性.</p>
<h4>2. 太多可能的Uncaught Exception</h4>
<p>     如果, 你调用了一个可能发生异常的函数, 但是却没有捕获这个异常, okey, Fatal Error了,  所以让我们的代码看起来:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
try {
} catch () {
}
....

try {
} catch () {
}
....
try {
} catch () {
}
</pre>
<p>     然而, 这个是可以经过良好设计避免的, 比如我在设计<a href="http://pecl.php.net/package/yaf" >Yaf</a>的时候, 就提供了全局异常处理, 也就是类似于, 你在最最顶层, 加上了一个try catch,  所有的异常错误逻辑都加到这个里面, 你也可以很方面的把你自己的异常加进去.  </p>
<h3>结论</h3>
<p>     经常有人批评我是俩面派,  呵呵, 但是在大家了解了上面的利弊以后, 是否也会和我一样认为: 这个事情没有定论呢? 一切从实际出发. <img src="http://www.laruence.com/wp-includes/images/smilies/icon_smile.gif"  alt=":)"  class="wp-smiley" /> </p>
<p>     说了这么多, 算是抛砖引玉, 欢迎补充, 交流: <a href="http://www.laruence.com" >here</a> or <a href="http://weibo.com/laruence" >here</a>.<br/>
   <script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, <a href="http://www.shibeike.net"  rel="external nofollow"  class="url" >treesky</a> writes: 前排留名啊。学习。HI群有点麻烦，能不能让我们也加入邮件列表啊。</li><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, darasion writes: 顶。
这个问题是我问的。

多谢，看完这文章明白多了。</li><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, lin writes: 能不能加入邮件列表和HI群</li><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, benson writes: 请问，作为一个production，异常处理的使用是为了在产品发生错误的时候能更好的提示用户，或者通知开发者，是这样理解吗？</li><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, <a href="http://blog.chedushi.com"  rel="external nofollow"  class="url" >岭南六少</a> writes: 哈哈，现在用hi的人貌似不是很多啊</li><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, <a href="http://www.kaiiak.com"  rel="external nofollow"  class="url" >xiaokaizi</a> writes: class xx{
    public $box[2] = 'fds';

    public function echso() {
        // ...
    }
}  这样定义类为什么报语法错误？

在zend_language_parser.c里，变量名是不允许带[]的，估计在词法分析那一步把$box[2]分割成了一个变量名，fds是值，到语法分析这步就出错了。
如果是这样原因。问题是为什么要在类的成员变量中这样分割，而普通变量缺不呢?</li><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @xiaokaizi class的属性声明必须使用常数, 见:http://www.php.net/manual/en/language.oop5.properties.php 

这个常数, 同时对值, 和, 名有效. :)</li><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, oboodo writes: 求hi群号，惠兄！</li><li><a href="http://www.laruence.com/2012/02/02/2515.html" >2012/02/02</a>, <a href="http://blankyao.com"  rel="external nofollow"  class="url" >blankyao</a> writes: 前几天遇到一个问题，类似下面的操作
stream1.close();
stream2.close();
stream3.close();
...

这几行代码都有可能抛出异常，但是抛出异常后也得保证后面的代码继续执行，所以就不能在外面搞一个try catch，所以现在是每一行都加一个tray catch，但是感觉比较ugly，有啥好的建议不？</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li><li><a href="http://www.laruence.com/2011/11/09/2277.html"  title="PHP原理之内存管理中难懂的几个点" >PHP原理之内存管理中难懂的几个点</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2012/02/02/2515.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>使用exit(-1)为什么得到255退出码?</title>
		<link>http://www.laruence.com/2012/02/01/2503.html</link>
		<comments>http://www.laruence.com/2012/02/01/2503.html#comments</comments>
		<pubDate>Wed, 01 Feb 2012 08:45:25 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[-1]]></category>
		<category><![CDATA[255]]></category>
		<category><![CDATA[exec]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[退出码]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2503</guid>
		<description><![CDATA[今天有人在<a href="http://www.weibo.com/laruence">微博</a>上问了一个问题, 使用:
<coolcode lang="php" linenum="off">
string exec ( string $command [, array &#038;$output [, int &#038;$return_var ]] )
</coolcode>
调用一个程序, 程序退出-1,  但是PHP得到的为什么是255?]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2012/02/01/2503.html"  title="Permanet Link to 使用exit(-1)为什么得到255退出码?" >http://www.laruence.com/2012/02/01/2503.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>今天有人在<a href="http://www.weibo.com/laruence" >微博</a>上问了一个问题, 使用:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
string exec ( string $command [, array &amp;$output [, int &amp;$return_var ]] )
</pre>
<p>调用一个程序, 程序退出-1,  但是PHP得到的为什么是255?</p>
<p>这个问题简单的说, 是因为exit或者main函数中的return, 只能使用0~255之间的值. -1 的unsigned值就是255.</p>
<p>那么复杂点的说呢?</p>
<p>我们知道, 在Shell中,  运行一个命令, 一个程序, 都是fork一个子进程(然后exec)来执行的, 而这个程序的退出码, 被Shell(父进程), 通过wait来收集而后报告给我们的.</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
pid_t wait(int *statloc);
</pre>
<p>而对于wait来说, 历史上原因, 他将通过statloc返回一个16bit的interge(现在也有用32位表示的, 但是会兼容已有的设计).  这16bits的interge中, 高8位就是程序退出的值(exit, 或者return), 而低八位表示导致这个程序退出的信号(其中一位表示是否有Core文件产生), 如果程序是正常退出, 那么低八位为0<font style="size:80%" >[1]</font>.</p>
<p>所以, 如果我们返回-1,  并且因为我们是正常退出, 所以Shell通过wait收集到的子进程退出状态是:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
11111111 00000000
</pre>
<p>而高八位作为unsigned, 就是255了.</p>
<p>另外, 补充一下, 在Linux的内建Shell命令中, 很多都会遵守一个退出状态码的约定, 具体的值对应的意思<font style="size:80%" >[2]</font>:</p>
<table>
<thead>
<tr>
<th>Exit Code Number</th>
<th>Meaning</th>
<th>Example</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
<tr>
<td><tt>1</tt></td>
<td>Catchall for general errors</td>
<td>let &#8220;var1 = 1/0&#8243;</td>
<td>Miscellaneous errors, such as &#8221;divide by zero&#8221; and other impermissible operations</td>
</tr>
<tr>
<td><tt>2</tt></td>
<td>Misuse of shell builtins (according to Bash documentation)</td>
<td>empty_function() {}</td>
<td>Seldom seen, usually defaults to exit code 1</td>
</tr>
<tr>
<td><tt>126</tt></td>
<td>Command invoked cannot execute</td>
<td></td>
<td>Permission problem or command is not an executable</td>
</tr>
<tr>
<td><tt>127</tt></td>
<td>&#8220;command not found&#8221;</td>
<td>illegal_command</td>
<td>Possible problem with <tt>$PATH</tt> or a typo</td>
</tr>
<tr>
<td><tt>128</tt></td>
<td>Invalid argument to <a href="http://tldp.org/LDP/abs/html/exit-status.html#EXITCOMMANDREF" >exit</a></td>
<td>exit 3.14159</td>
<td><strong>exit</strong> takes only integer args in the range 0 &#8211; 255 (see first footnote)</td>
</tr>
<tr>
<td><tt>128+n</tt></td>
<td>Fatal error signal &#8221;n&#8221;</td>
<td><em>kill -9</em> <tt>$PPID</tt> of script</td>
<td><tt><strong>$?</strong></tt> returns 137 (128 + 9)</td>
</tr>
<tr>
<td><tt>130</tt></td>
<td>Script terminated by Control-C</td>
<td></td>
<td>Control-C is fatal error signal 2, (130 = 128 + 2, see above)</td>
</tr>
<tr>
<td><tt>255*</tt></td>
<td>Exit status out of range</td>
<td>exit -1</td>
<td><strong>exit</strong> takes only integer args in the range 0 &#8211; 255</td>
</tr>
</tbody>
</table>
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>[1]: <a href="http://stackoverflow.com/questions/2726447/why-is-the-exit-code-255-instead-of-1-in-perl" >http://stackoverflow.com/questions/2726447/why-is-the-exit-code-255-instead-of-1-in-perl</a></li>
<li>[2]: <a href="http://tldp.org/LDP/abs/html/exitcodes.html" >http://tldp.org/LDP/abs/html/exitcodes.html</a></li>
</ul>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/01/2503.html" >2012/02/02</a>, 唐僧 writes: 你太牛逼了。膜拜！！！</li><li><a href="http://www.laruence.com/2012/02/01/2503.html" >2012/02/02</a>, <a href="http://kimwu.sinaapp.com"  rel="external nofollow"  class="url" >熊少</a> writes: 哈 了解了</li><li><a href="http://www.laruence.com/2012/02/01/2503.html" >2012/02/02</a>, <a href="http://blog.chedushi.com"  rel="external nofollow"  class="url" >岭南六少</a> writes: 又充了下电啦
赞</li><li><a href="http://www.laruence.com/2012/02/01/2503.html" >2012/02/03</a>, ooxx writes: 这个不错</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li><li><a href="http://www.laruence.com/2011/11/09/2277.html"  title="PHP原理之内存管理中难懂的几个点" >PHP原理之内存管理中难懂的几个点</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2012/02/01/2503.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PHP的历史</title>
		<link>http://www.laruence.com/2012/01/11/2482.html</link>
		<comments>http://www.laruence.com/2012/01/11/2482.html#comments</comments>
		<pubDate>Wed, 11 Jan 2012 03:14:30 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[转载]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP 3.0]]></category>
		<category><![CDATA[PHP 4]]></category>
		<category><![CDATA[PHP/FI]]></category>
		<category><![CDATA[历史]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2482</guid>
		<description><![CDATA[了解下PHP的历史, 有助于更加深刻的了解PHP发展到今天的轨迹,  下面的文字都是从<a href="http://www.php.net/manual/zh/history.php">» PHP手册</a>中转载过来的.

PHP 在过去的几年里走过了漫长的道路。成长为处理 web 的最卓越的语言并非易事。如果对 PHP 如何发展到今天很感兴趣，那么请继续读下去吧。以前的 PHP 发行版可以在 <a herf="http://museum.php.net/">» PHP 博物馆</a>找到。]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2012/01/11/2482.html"  title="Permanet Link to PHP的历史" >http://www.laruence.com/2012/01/11/2482.html</a></li>
<li>文章转自: <a href="http://www.php.net/manual/zh/history.php" >PHP 及其相关工程的历史</a></li>
</ul></div>
<p>了解下PHP的历史, 有助于更加深刻的了解PHP发展到今天的轨迹,  下面的文字都是从<a href="http://www.php.net/manual/zh/history.php" >» PHP手册</a>中转载过来的.</p>
<p>PHP 在过去的几年里走过了漫长的道路。成长为处理 web 的最卓越的语言并非易事。如果对 PHP 如何发展到今天很感兴趣，那么请继续读下去吧。以前的 PHP 发行版可以在 <a herf="http://museum.php.net/" >» PHP 博物馆</a>找到。</p>
<h3>PHP/FI</h3>
<p>PHP 继承自一个老的工程，名叫 PHP/FI。PHP/FI 在 1995 年由 Rasmus Lerdorf 创建，最初只是一套简单的 Perl 脚本，用来跟踪访问他主页的人们的信息。它给这一套脚本取名为“Personal Home Page Tools”。随着更多功能需求的增加，Rasmus 写了一个更大的 C 语言的实现，它可以访问数据库，可以让用户开发简单的动态 Web 程序。Rasmus » 发布了 PHP/FI 的源代码，以便每个人都可以使用它，同时大家也可以修正它的 Bug 并且改进它的源代码。</p>
<p>PHP/FI，一个专为个人主页／表单提供解释程序的程序，已经包含了今天 PHP 的一些基本功能。它有着 Perl 样式的变量，自动解释表单变量，并可以嵌入 HTML。语法本身与 Perl 很相似，但是它很有限，很简单，还稍微有些不协调。</p>
<p>到1997年，PHP/FI 2.0，也就是它的 C 语言实现的第二版在全世界已经有几千个用户（估计）和大约 50,000 个域名安装，大约是 Internet 所有域名的 1%。但是那时只有几个人在为该工程撰写少量当代码，它仍然只是一个人的工程。</p>
<p>PHP/FI 2.0 在经历了数个 beta 版本的发布后于 1997 年 11 月发布了官方正式版本。不久，PHP 3.0 的第一个 alpha 版本的发布，PHP 从此走向了成功。</p>
<h3>PHP 3</h3>
<p>PHP 3.0 是类似于当今 PHP 语法结构的第一个版本。Andi Gutmans 和 Zeev Suraski 在为一所大学的项目中开发电子商务程序时发现 PHP/FI 2.0 功能明显不足，于是他们重写了代码。这就是 PHP 3.0。经过Andi，Rasmus 和 Zeev 一系列的努力，考虑到 PHP/FI 已存在的用户群，他们决定联合发布 PHP 3.0 作为 PHP/FI 2.0 的官方后继版本。而 PHP/FI 2.0 的进一步开发几乎终止了。</p>
<p>PHP 3.0 的一个最强大的功能是它的可扩展性。除了给最终用户提供数据库、协议和 API 的基础结构，它的可扩展性还吸引了大量的开发人员加入并提交新的模块。后来证实，这是 PHP 3.0 取得巨大成功的关键。PHP 3.0 中的其它关键功能包括面向对象的支持和更强大和协调的语法结构。</p>
<p>这个全新的语言伴随着一个新的名称发布。它从 PHP/FI 2.0 的名称中移去了暗含“本语言只限于个人使用”的部分。它被命名为简单的缩写“PHP”。这是一种递归的缩写，它的全称是——PHP: Hypertext Preprocessor。</p>
<p>1998 年末，PHP 的安装人数几近 10,000，有大约 100,000 个网站报告他们使用了 PHP。在 PHP 3.0 的顶峰，Internet 上 10% 的 web 服务器上都安装了它。</p>
<p>约九个月的公开测试后，官方于 1998 年 6 月正式发布 PHP 3.0。</p>
<h3>PHP 4</h3>
<p>1998 年的冬天，PHP 3.0 官方发布不久，Andi Gutmans 和 Zeev Suraski 开始重新编写 PHP 代码。设计目标是增强复杂程序运行时的性能和 PHP 自身代码的模块性。PHP 3.0 的新功能和广泛的第三方数据库、API的支持使得这样程序的编写成为可能，但是 PHP 3.0 没有高效处理如此复杂程序的能力。</p>
<p>新的被称为“Zend Engine”（这是 Zeev 和 Andi 的缩写）的引擎，成功的实现了设计目标，并在 1999 年中期首次引入 PHP。基于该引擎并结合了更多新功能的 PHP 4.0，在 PHP 3.0 发布两年后，于2000年5月发布了官方正式版本。除了更高的性能以外，PHP 4.0 还包含了其它一些关键功能，比如：支持更多的 web 服务器；HTTP Sessions 支持；输出缓冲；更安全的处理用户输入的方法；一些新的语言结构。</p>
<p>今天，已经有 10,000 名开发人员（估计）和几百万网站报告已安装了 PHP，占整个 Internet 域名的 20%。</p>
<p>PHP 的开发小组有很多优秀的开发人员，同时还有大量的优秀人才在进行 PHP 相关工程的开发工作，如 PEAR 和 PHP 文档的工程。</p>
<h3>PHP 5</h3>
<p>PHP 5 在长时间的开发及多个预发布版本后，于 2004 年 7 月发布正式版本。它的核心是 Zend 引擎 2 代，引入了新的对象模型和大量新功能。</p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/01/11/2482.html" >2012/01/11</a>, <a href="http://hi.baidu.com/higkoo"  rel="external nofollow"  class="url" >higkoo</a> writes: 好事多磨，愿PHP越来越好，越来越强！</li><li><a href="http://www.laruence.com/2012/01/11/2482.html" >2012/01/11</a>, <a href="http://deloz.net"  rel="external nofollow"  class="url" >Deloz</a> writes: C是很多语言的基础呀.</li><li><a href="http://www.laruence.com/2012/01/11/2482.html" >2012/01/11</a>, <a href="http://waibo.net/"  rel="external nofollow"  class="url" >Rhythm</a> writes: 总是能多些思考，感谢。</li><li><a href="http://www.laruence.com/2012/01/11/2482.html" >2012/01/12</a>, <a href="http://blog.netoearth.com/html/201201/php%e7%9a%84%e5%8e%86%e5%8f%b2.htm"  rel="external nofollow"  class="url" >PHP的历史</a> writes: [...] 本文地址: http://www.laruence.com/2012/01/11/2482.html [...]</li><li><a href="http://www.laruence.com/2012/01/11/2482.html" >2012/01/13</a>, harveyzh writes: 为什么创造php的作者 Rasmus Lerdorf 离开了？</li><li><a href="http://www.laruence.com/2012/01/11/2482.html" >2012/01/17</a>, <a href="http://gnroed@gmail.com"  rel="external nofollow"  class="url" >nroe</a> writes: 我们在更新到　５.３.９　版本后发现，出现很多　“no buffer space available”　的错误提示，导致　TCP/IP SOCKET　无法创建，服务无法正常运行。
请问下　5.3.9　在创建　SOCKET　的是否是不是加大了缓冲区？</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/09/19/2148.html"  title="PHP的版本发布历程" >PHP的版本发布历程</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2012/01/11/2482.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>如何设置一个严格30分钟过期的Session</title>
		<link>http://www.laruence.com/2012/01/10/2469.html</link>
		<comments>http://www.laruence.com/2012/01/10/2469.html#comments</comments>
		<pubDate>Tue, 10 Jan 2012 07:02:17 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[COOKIE]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[session]]></category>
		<category><![CDATA[过期]]></category>
		<category><![CDATA[面试题]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2469</guid>
		<description><![CDATA[今天在我的微博(<a href="http://t.sina.com.cn/laruence">Laruence</a>)上发出一个问题:
<blockquote>
我在面试的时候, 经常会问一个问题: "如何设置一个30分钟过期的Session?", 大家不要觉得看似简单, 这里面包含的知识挺多, 特别适合考察基本功是否扎实, 谁来回答试试? 呵呵
</blockquote>

   为什么问这个问题呢?  1. 我在Twitter上看到了有人讨论这个<a href="http://stackoverflow.com/questions/520237/how-do-i-expire-a-php-session-after-30-minutes">问题</a>, 2 想起来我经常问这个问题, 所以~~

   在这里, 我来解答下这个题目.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2012/01/10/2469.html"  title="Permanet Link to 如何设置一个严格30分钟过期的Session" >http://www.laruence.com/2012/01/10/2469.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    今天在我的微博(<a href="http://t.sina.com.cn/laruence" >Laruence</a>)上发出一个问题:</p>
<blockquote><p>
我在面试的时候, 经常会问一个问题: &#8220;如何设置一个30分钟过期的Session?&#8221;, 大家不要觉得看似简单, 这里面包含的知识挺多, 特别适合考察基本功是否扎实, 谁来回答试试? 呵呵
</p></blockquote>
<p>   为什么问这个问题呢?  1. 我在Twitter上看到了有人讨论这个<a href="http://stackoverflow.com/questions/520237/how-do-i-expire-a-php-session-after-30-minutes" >问题</a>, 2 想起来我经常问这个问题, 所以~~</p>
<p>   在这里, 我来解答下这个题目.</p>
<h3>第一种回答</h3>
<p>那么, 最常见的一种回答是: 设置Session的过期时间, 也就是<a href="http://www.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime" >session.gc_maxlifetime</a>,  这种回答是不正确的, 原因如下:</p>
<p>   1.  首先, 这个PHP是用一定的概率来运行session的gc的, 也就是session.gc_probability和session.gc_divisor(介绍参看<a href="http://www.laruence.com/2011/03/29/1949.html" > 深入理解PHP原理之Session Gc的一个小概率Notice</a>), 这个默认的值分别是1和100, 也就是有1%的机会, PHP会在一个Session启动时, 运行Session gc. 不能保证到30分钟的时候一定会过期.</p>
<p>   2. 那设置一个大概率的清理机会呢?  还是不妥, 为什么?  因为PHP使用stat Session文件的修改时间来判断是否过期, 如果增大这个概率一来会降低性能, 二来, PHP使用&#8221;一个&#8221;文件来保存和一个会话相关的Session变量, 假设我5分钟前设置了一个a=1的Session变量, 5分钟后又设置了一个b=2的Seesion变量, 那么这个Session文件的修改时间为添加b时刻的时间, 那么a就不能在30分钟的时候, 被清理了. 另外还有下面第三个原因.</p>
<p>   3. PHP默认的(Linux为例), 是使用/tmp 作为Session的默认存储目录, 并且手册中也有如下的描述:</p>
<blockquote><p>
Note: 如果不同的脚本具有不同的 session.gc_maxlifetime 数值但是共享了同一个地方存储会话数据，则具有最小数值的脚本会清理数据。此情况下，与 session.save_path 一起使用本指令。
</p></blockquote>
<p>      也就是说, 如果有俩个应用都没有指定自己独立的save_path, 一个设置了过期时间为2分钟(假设为A), 一个设置为30分钟(假设为B), 那么每次当A的Session gc运行的时候, 就会同时删除属于应用B的Session files.</p>
<p>      所以, 第一种答案是不&#8221;完全严格&#8221;正确的.</p>
<h3>第二种答案</h3>
<p>还有一种常见的答案是: 设置Session ID的载体, Cookie的过期时间, 也就是<a href="http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime" >session.cookie_lifetime</a>.  这种回答也是不正确的, 原因如下:</p>
<p>    这个过期只是Cookie过期,  换个说法这点就考察Cookie和Session的区别, Session过期是服务器过期, 而Cookie过期是客户端(浏览器)来保证的, 即使你设置了Cookie过期, 这个只能保证标准浏览器到期的时候, 不会发送这个Cookie(包含着Session ID), 而如果通过构造请求, 还是可以使用这个Session ID的值.</p>
<h3>第三种答案</h3>
<p>使用memcache, redis等, okey, 这种答案是一种正确答案.  不过, 很显然出题者肯定还会接着问你, 如果只是使用PHP呢?</p>
<h3>第四种答案</h3>
<p>当然, 面试不是为了难道你, 而是为了考察思考的周密性. 在这个过程中我会提示出这些陷阱,  所以一般来说, 符合题意的做法是:</p>
<p>    1. 设置Cookie过期时间30分钟, 并设置Session的lifetime也为30分钟.</p>
<p>    2. 自己为每一个Session值增加Time stamp.</p>
<p>    3. 每次访问之前, 判断时间戳. </p>
<p>最后, 有同学问,  为什么要设置30分钟的过期时间:  这个, 首先这是为了面试, 第二, 实际使用场景的话, 比如30分钟就过期的优惠劵? </p>
<p>thanks <img src="http://www.laruence.com/wp-includes/images/smilies/icon_smile.gif"  alt=":)"  class="wp-smiley" /> </p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/10</a>, peng writes: thanks</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/10</a>, <a href="http://weibo.com/pangee"  rel="external nofollow"  class="url" >pangee</a> writes: 好吧。学习了。</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/10</a>, <a href="http://blog.webfuns.net"  rel="external nofollow"  class="url" >tomheng</a> writes: 应该是stackoverflow吧</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/10</a>, <a href="http://www.cxphp.com"  rel="external nofollow"  class="url" >鑫爷</a> writes: 好东西啊。学习了。。</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/10</a>, <a href="http://www.shibeike.net"  rel="external nofollow"  class="url" >treesky</a> writes: 引用部分的那个歪字体看起来十分费劲。</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/10</a>, heyli writes: 第一回答 php.ini 修改 至于修改那里 不记得要回去查下
第二 要严格的 我会考虑写进数据库</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/10</a>, wclssdn writes: 好吧.. 我的第一反应就是session中存时间戳.. 如果session中变量需要设置过期.. 那就为变量添加时间戳.... 
貌似这个方法最可靠了~~ 
使用内存缓存之类的... 是使用它们替换session存储位置? 
那同样没有设置过期时间的地方... 只能再此基础上封装成类.. 在方法中添加过期时间. 传递给redis.. 而这样.. 就跟添加时间戳没区别了...</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/11</a>, 四不象 writes: 为什么我觉得第一种回答的第一点不成立呢。那个设置是gc，垃圾回收，并非是没被回收的session文件不会过期。PHP的session默认的file引擎在读取session文件前还是会判断文件最后修改时间的，如果超出session.gc_maxlifetime就不会读取这个session文件</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/11</a>, <a href="http://weibo.com/enzohere"  rel="external nofollow"  class="url" >enzo</a> writes: session.gc_maxlifetime既然不能严格控制session的过期时间，这算不算bug？我的愚建是既然有个这样的配置就应该保证这个配置对应的功能能起到确定的作用。</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/12</a>, silentime writes: 实际的应用场景如果需要严格过期的话，应该不会用session机制把？</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/12</a>, <a href="http://blog.byedown.com/topics/489.html"  rel="external nofollow"  class="url" >如何设置一个严格30分钟过期的Session | Just Me</a> writes: [...] 原文地址: http://www.laruence.com/2012/01/10/2469.html [...]</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/01/31</a>, <a href="http://sk80.sinaapp.com/?p=51"  rel="external nofollow"  class="url" >如何设置一个严格30分钟过期的Session | Only WordPress</a> writes: [...] 来源：http://www.laruence.com/2012/01/10/2469.html 第一种回答 [...]</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/02/01</a>, <a href="http://www.tageta.com"  rel="external nofollow"  class="url" >klvoek</a> writes: 第三种答案求深入</li><li><a href="http://www.laruence.com/2012/01/10/2469.html" >2012/02/01</a>, <a href="http://www.52sql.com/?p=272"  rel="external nofollow"  class="url" >如何设置一个严格30分钟过期的Session | 迈克</a> writes: [...] 来源：http://www.laruence.com/2012/01/10/2469.html [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/03/29/1949.html"  title="深入理解PHP原理之Session Gc的一个小概率Notice" >深入理解PHP原理之Session Gc的一个小概率Notice</a></li><li><a href="http://www.laruence.com/2009/12/05/1172.html"  title="PHP5.2.x + APC的一个bug的定位" >PHP5.2.x + APC的一个bug的定位</a></li><li><a href="http://www.laruence.com/2009/07/13/976.html"  title="PHP Session的一个警告" >PHP Session的一个警告</a></li><li><a href="http://www.laruence.com/2008/04/04/17.html"  title="在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究" >在PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2012/01/10/2469.html/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>2012年1月全球www网站技术报告</title>
		<link>http://www.laruence.com/2012/01/07/2453.html</link>
		<comments>http://www.laruence.com/2012/01/07/2453.html#comments</comments>
		<pubDate>Sat, 07 Jan 2012 09:21:15 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[转载]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[排行]]></category>
		<category><![CDATA[统计]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2453</guid>
		<description><![CDATA[ <a href="http://w3techs.com/">W3Techs</a>在2012年1月7日, 发出最新的"全球www网站技术报告".

    该统计基于对全球Alexa排名前100W的www网站做分析而得出.

    统计报告(<a href="http://w3techs.com/technologies/overview/programming_language/all">Usage of server-side programming languages for websites</a>)显示, 相比2011年12月, 使用PHP构建的前100W名中的网站,又增长了约0.1%(30个), PHP占据的份额增长至77.3%, 依旧排名第一.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2012/01/07/2453.html"  title="Permanet Link to 2012年1月全球www网站技术报告" >http://www.laruence.com/2012/01/07/2453.html</a></li>
<li>文章转自: <a href="http://w3techs.com/technologies/overview/programming_language/all" >Usage of server-side programming languages for websites</a></li>
</ul></div>
<p>
    <a href="http://w3techs.com/" >W3Techs</a>在2012年1月7日, 发出最新的&#8221;全球www网站技术报告&#8221;.</p>
<p>    该统计基于对全球Alexa排名前100W的www网站做分析而得出.</p>
<p>    统计报告(<a href="http://w3techs.com/technologies/overview/programming_language/all" >Usage of server-side programming languages for websites</a>)显示, 相比2011年12月, 使用PHP构建的前100W名中的网站,又增长了约0.1%(30个), PHP占据的份额增长至77.3%, 依旧排名第一.<br/>
    <div id="attachment_2454"  class="wp-caption aligncenter"  style="width: 534px" ><a href="http://laruence-wordpress.stor.sinaapp.com/uploads/W3techs统计.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/W3techs统计.png"  alt=""  title="W3techs统计"  width="524"  height="244"  class="size-full wp-image-2454" /></a><p class="wp-caption-text" >W3Techs全球www技术统计报告2012年1月</p></div></p>
<p>    下图显示了1年来的各语言的趋势(来自:<a href="http://w3techs.com/technologies/history_overview/programming_language" >Historical trends in the usage of server-side programming languages for websites</a>):<br/>
 <div id="attachment_2456"  class="wp-caption aligncenter"  style="width: 310px" ><a href="http://laruence-wordpress.stor.sinaapp.com/uploads/www技术趋势1.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/www技术趋势1-300x71.png"  alt=""  title="www技术趋势"  width="300"  height="71"  class="size-medium wp-image-2456" /></a><p class="wp-caption-text" >历史发展趋势</p></div></p>
<p>    而, 下图是使用的PHP版本统计:<br/>
<div id="attachment_2457"  class="wp-caption aligncenter"  style="width: 449px" ><a href="http://laruence-wordpress.stor.sinaapp.com/uploads/PHP版本.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/PHP版本.png"  alt=""  title="PHP版本"  width="439"  height="146"  class="size-full wp-image-2457" /></a><p class="wp-caption-text" >PHP版本对比</p></div></p>
<p>    可见, 已经全面进入PHP5的时代了,但使用PHP4的网站还是有很大的数量.  </p>
<p>    上面提到的是www网站的服务端编程语言的对比, 而对于Client端的编程语言, 依旧还是Javascript的天下, 占到了90%以上:<br/>
     <div id="attachment_2463"  class="wp-caption aligncenter"  style="width: 399px" ><a href="http://laruence-wordpress.stor.sinaapp.com/uploads/未命名图片.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/未命名图片.png"  alt=""  title="Client端编程语言"  width="389"  height="147"  class="size-full wp-image-2463" /></a><p class="wp-caption-text" >Client端编程语言</p></div></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/07</a>, <a href="http://www.xingdonghai.cn"  rel="external nofollow"  class="url" >伴夜</a> writes: 支持PHP</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/07</a>, <a href="http://www.cnxct.com"  rel="external nofollow"  class="url" >CFC4N</a> writes: 1,perl居然比python多，意料之外(我见识短)。
2,ASP.NET递减，JAVA缓慢增长。
3,ColdFusion居然出现了，而且，排第四，惊讶！(我见识短)。</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/08</a>, dryangkun writes: Hypertext Preprocessor从名字上就能看出PHP的定位，加油,PHP...</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/08</a>, <a href="http://www.hostsir.com"  rel="external nofollow"  class="url" >域名注册</a> writes: asp.net的上升趋势不能忽视，包含asp吗？</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/08</a>, <a href="http://www.tanglei.name"  rel="external nofollow"  class="url" >tanglei</a> writes: php用于快速迭代方面实在有优势。不过能否知道有多少在用php的面向对象编程呢?所在公司用php开发没有利用其OO方面的特性。</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/09</a>, nardoo writes: 用OO方面的特性的公司比较少吧， 受限于公司的历史代码，重构也比较麻烦。</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/09</a>, <a href="http://waibo.net/"  rel="external nofollow"  class="url" >Rhythm</a> writes: PHP和JS必须要双精！双精了以后，就不愁以后没前途了。</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/09</a>, <a href="http://blog.iterse.com"  rel="external nofollow"  class="url" >Iterse's blog</a> writes: 支持下！</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/15</a>, cers writes: 各种语言的设计初衷和目的不同，PHP就是为Web而生的，其它的语言则不是</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/01/17</a>, <a href="http://litefeel.com"  rel="external nofollow"  class="url" >lite3</a> writes: 虽然我是做AS的,但是对于网站,前端还是建议用HTML,JS, Flash要做游戏的</li><li><a href="http://www.laruence.com/2012/01/07/2453.html" >2012/02/03</a>, <a href="http://www.hihoku.com"  rel="external nofollow"  class="url" >蚂蚁</a> writes: 哈哈 python 居然有下降的趋势，ColdFusion 搞不懂为什么会排在这里</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li><li><a href="http://www.laruence.com/2011/11/09/2277.html"  title="PHP原理之内存管理中难懂的几个点" >PHP原理之内存管理中难懂的几个点</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2012/01/07/2453.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</title>
		<link>http://www.laruence.com/2011/12/30/2440.html</link>
		<comments>http://www.laruence.com/2011/12/30/2440.html#comments</comments>
		<pubDate>Fri, 30 Dec 2011 09:05:29 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[Hash冲突]]></category>
		<category><![CDATA[patch]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[拒绝服务攻击]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2440</guid>
		<description><![CDATA[   由我前面的俩篇文章介绍(<a href="http://www.laruence.com/2011/12/29/2412.html">通过构造Hash冲突实现各种语言的拒绝服务攻击</a>, <a href="http://www.laruence.com/2011/12/30/2435.html">PHP数组的Hash冲突实例 </a> ),  这个攻击方法危害很高, 攻击成本也很小.  一个台式机可以轻松搞垮数十台, 上百台服务器.  
   
     而和Pierre沟通后, 官方开发组不会为此发布PHP 5.2.18, 但是目前还是由不少公司还在使用5.2,  所以我特将dmitry为5.4写的patch, 分别apply到5.2上.

     大家如果有用5.2的, 如果被此类攻击威胁, 可以打上下面的patch,  PHP5.3的, 可以考虑升级到5.3.9, 已经包含了此patch(因为5.3.9目前是RC状态, 所以如果不愿意升级, 也可以参照这个patch自己为5.3写一个): 

     <a href="https://github.com/laruence/laruence.github.com/tree/master/php-5.2-max-input-vars">https://github.com/laruence/laruence.github.com/tree/master/php-5.2-max-input-vars</a>
    
     另外, 其他语言java, ruby等, 请各位也预先想好对策, 限制post_size是治标不治本的方法, 不过可以用来做临时解决方案.

thanks]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/12/30/2440.html"  title="Permanet Link to PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >http://www.laruence.com/2011/12/30/2440.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
     由我前面的俩篇文章介绍(<a href="http://www.laruence.com/2011/12/29/2412.html" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a>, <a href="http://www.laruence.com/2011/12/30/2435.html" >PHP数组的Hash冲突实例 </a> ),  这个攻击方法危害很高, 攻击成本也很小.  一个台式机可以轻松搞垮数十台, 上百台服务器.  </p>
<p>     而和Pierre沟通后, 官方开发组不会为此发布PHP 5.2.18, 但是目前还是由不少公司还在使用5.2,  所以我特将dmitry为5.4写的patch, 分别apply到5.2上.</p>
<p>     大家如果有用5.2的, 如果被此类攻击威胁, 可以打上下面的patch,  PHP5.3的, 可以考虑升级到5.3.9, 已经包含了此patch(因为5.3.9目前是RC状态, 所以如果不愿意升级, 也可以参照这个patch自己为5.3写一个): </p>
<p>     <a href="https://github.com/laruence/laruence.github.com/tree/master/php-5.2-max-input-vars" >https://github.com/laruence/laruence.github.com/tree/master/php-5.2-max-input-vars</a></p>
<p>     补充一下(2012年1月8日): 如果你使用的是Windows下的PHP, 或者其他原因导致你不方便采用打patch的方法, 也可以采用修改PHP的配置max_input_time为一个较小的值来缓解此类攻击带来的影响.</p>
<p>     另外, 其他语言java, ruby等, 请各位也预先想好对策, 限制post_size是治标不治本的方法, 不过可以用来做临时解决方案.</p>
<p>thanks</p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/30</a>, cha369 writes: 鸟哥效率啊，造福大众</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/30</a>, <a href="http://blog.thephper.com"  rel="external nofollow"  class="url" >板子</a> writes: 鸟哥，这两篇文章一发，大家都不得不升级了 
攻击门槛被降低到约等于0了</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/30</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @板子 不能怨我啊, 这个方法是国外曝出来的.....</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/30</a>, -_- writes: 弱弱的问一下 如何给线上运行的PHP打path</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/31</a>, 蘑菇 writes: 呃,php 5.3.9 在哪?</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/31</a>, coralzd writes: cd Php-5.2.17 ;
执行patch  -p1  php-5.2.17-max-input-vars.patch  
一直在那里卡住！</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/31</a>, Anders writes: 貌似必须restart 才行啊， reload都不行呢。</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/31</a>, 饼饼 writes: patch -p1 &lt; laruence-laruence.github.com-43969a1/php-5.2-max-input-vars/php-5.2.17-max-input-vars.patch
can&#039;t find file to patch at input line 4
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff -u -r php-5.2.17/configure php-5.2.17-patched/configure
|--- php-5.2.17/configure       2011-01-07 07:04:43.000000000 +0800
|+++ php-5.2.17-patched/configure       2011-12-31 11:46:11.000000000 +0800
--------------------------
File to patch:


不行挖。。</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/31</a>, boyaa writes: it is can not make effect even though I patched the php-5.2.10 successfully !</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2011/12/31</a>, Justin writes: sed -i "s/PHP_EXTRA_VERSION=\"\"/PHP_EXTRA_VERSION=\"p1\"/" ./configure
sed -i "s/PHP_EXTRA_VERSION=\"\"/PHP_EXTRA_VERSION=\"p1\"/" ./configure.in
sed -i "s/define PHP_EXTRA_VERSION \"\"/define PHP_EXTRA_VERSION \"p1\"/" ./main/php_version.h
sed -i "s/long max_input_nesting_level;/&amp;\n\tlong max_input_vars;/" ./main/php_globals.h

sed -ie "/Z_TYPE_PP(gpc_element_p) != IS_ARRAY) {/a\\\t\t\t\t\tif (zend_hash_num_elements(symtable1) &gt;= PG(max_input_vars)) {\n\t\t\t\t\t\tphp_error_docref(NULL TSRMLS_CC, E_ERROR, \"Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.\", PG(max_input_vars));\n\t\t\t\t\t}" ./main/php_variables.c

sed -ie "/zval_ptr_dtor(&amp;gpc_element);/{n; s/} else {/&amp;\n\t\t\t\tif (zend_hash_num_elements(symtable1) &gt;= PG(max_input_vars)) {\n\t\t\t\t\tphp_error_docref(NULL TSRMLS_CC, E_ERROR, \"Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.\", PG(max_input_vars));\n\t\t\t\t}/;}" ./main/php_variables.c

sed -ie "/PHP_INI_BEGIN()/{n; s/$/&amp;\n\tSTD_PHP_INI_ENTRY(\"max_input_vars\",         \"1000\",     PHP_INI_SYSTEM|PHP_INI_PERDIR,      OnUpdateLongGEZero, max_input_vars, php_core_globals, core_globals)/;}" ./main/main.c</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/02</a>, 不懂 writes: 鸟哥,问你个问题:
在网站访问量比较大的时候,网站应用了伪静态和不用伪静态对主机的性能影响的区别有多大?
应用伪静态会多占用服务器的CPU?</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/04</a>, 一寒 writes: linux的还有办法打补丁重编译，windows下的php5.2.17怎么编译？现在好多加密程序只支持PHP5.2X系列，用不了5.3，而官方又不给5.2.17提供解决办法。强烈建议出一个经验证的完整的windows编译方法</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/04</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @一寒 Windows下, 可以考虑安装suhosin扩展: http://www.hardened-php.net/suhosin/ 它也有类似的suhosin.post.max_vars的设置</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/04</a>, Anonymous writes: 发现这个补丁在post参数超过设置时，错误信息并不能显示在浏览器里（display_errors已经打开），nginx日志为：
2012/01/04 19:32:05 [error] 16816#0: *256659 FastCGI sent in stderr: "PHP Fatal error:  Unknown: Input variables exceeded 1.
To increase the limit change max_input_vars in php.ini. in Unknown on line 0" while reading response header from upstream, cl
ient: *****, server: $host, request: "POST /input_vars.php HTTP/1.1", upstream: 
......

2012/01/04 19:32:05 [error] 16816#0: *256659 upstream sent unexpected FastCGI record: 3 while reading response header from up
stream, client: ******, server: $host, request: "POST /input_vars.php HTTP/1.1", upstream: 
......</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/04</a>, 三少 writes: 发现这个补丁在参数超过设置时错误信息并不能显示出来。

2012/01/04 19:32:05 [error] 16816#0: *256659 FastCGI sent in stderr: "PHP Fatal error:  Unknown: Input variables exceeded 1.
To increase the limit change max_input_vars in php.ini. in Unknown on line 0" while reading response header from upstream, cl
ient: *****, server: $host, request: "POST /input_vars.php HTTP/1.1", upstream: 


2012/01/04 19:32:05 [error] 16816#0: *256659 upstream sent unexpected FastCGI record: 3 while reading response header from up
stream, client: *****, server: $host, request: "POST /input_vars.php HTTP/1.1", upstream:</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/06</a>, rui7905 writes: 5.2.14打过补丁之后，发现file_get_contents函数会报“URL File-Access is Disabled”的错误，修改php.ini的allow_url_include为On之后，就好了。但是补丁之前的allow_url_include也是Off，看过补丁代码也没发现跟这个有关的地方，很奇怪……</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/06</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @rui7905 你打完补丁以后, make clean了么</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/07</a>, <a href="http://blog.jobbole.com/11516/"  rel="external nofollow"  class="url" >PHP哈希表碰撞攻击原理 - 博客 - 伯乐在线</a> writes: [...] 针对POST方式的哈希碰撞攻击，目前PHP的防护措施是控制POST数据的数量。在&gt;=PHP5.3.9的版本中增加了一个配置项max_input_vars，用于标识一次http请求最大接收的参数个数，默认为1000。因此PHP5.3.x的用户可以通过升级至5.3.9来避免哈希碰撞攻击。5.2.x的用户可以使用这个patch：http://www.laruence.com/2011/12/30/2440.html。 [...]</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/07</a>, <a href="http://blog.jobbole.com/11535/"  rel="external nofollow"  class="url" >PHP哈希表碰撞攻击原理 - 博客 - 伯乐在线</a> writes: [...] 针对POST方式的哈希碰撞攻击，目前PHP的防护措施是控制POST数据的数量。在&gt;=PHP5.3.9的版本中增加了一个配置项 max_input_vars，用于标识一次http请求最大接收的参数个数，默认为1000。因此PHP5.3.x的用户可以通过升级至5.3.9来避 免哈希碰撞攻击。5.2.x的用户可以使用这个patch：http://www.laruence.com/2011/12/30/2440.html。 [...]</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/08</a>, <a href="https://lauyu.me/2012/01/08/installed-to-prevent-denial-of-service-attacks-hash-conflict-php-patch/"  rel="external nofollow"  class="url" >安装防止Hash冲突拒绝服务攻击的PHP Patch &laquo; Lauyu的茶几</a> writes: [...] 在随后几天laruence放出了PHP对应的补丁,以解决这一问题. [...]</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/08</a>, <a href="http://blog.mrbird.org/2012/01/installed-to-prevent-denial-of-service-attacks-hash-conflict-php-patch/"  rel="external nofollow"  class="url" >安装防止Hash冲突拒绝服务攻击的PHP Patch | Mr.Bird</a> writes: [...] 在之后laruence放出了PHP对应的补丁,以解决这一问题. [...]</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/09</a>, zlsky writes: 我打了5.2.17的补丁之后,php的session就无法保存了.
大致看了一下应该是cookie的session id 无法映射到服务器里面的session值....
每当页面跳转的时候session值就全部丢失了?会是什么原因造成的.</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/01/12</a>, easyboy writes: centos下用yum安装的PHP能打补丁吗？都不知道怎么进入PHP src目录，求教！～</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/02/03</a>, <a href="http://none"  rel="external nofollow"  class="url" >none</a> writes: please fix this bug https://bugs.php.net/bug.php?id=60708 in you https://github.com/laruence/laruence.github.com/tree/master/php-5.2-max-input-vars patch</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/02/03</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @none 我为5.2提供的patch, 不受此影响. thanks :)</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/02/03</a>, George writes: Hello Laruence,

There were a related vulnerability CVE-2012-0830 for this patch.

May you mind to back-ported the change for PHP 5.2.17 too?

Thank you very much for your kind attention

Regards
George</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/02/04</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >laruence</a> writes: @George 
hello, there is no such issue in this patch, so plz don't worry. :)</li><li><a href="http://www.laruence.com/2011/12/30/2440.html" >2012/02/04</a>, George writes: Hello Laruence,

您好， 首先謝謝您的回覆, 有少少問題欲請教 - 

在您的 5.2.17 patch 裡， 於 php_error_docref ， 您使用了 E_ERROR (而不是 PHP 5.3.9 原本的 E_WARNING)

我們驗過， 似乎 E_ERROR 是會中止 c 程式執行，所以沒有運行有問題的 Z_ARRVAL_PP；

而 E_WARNING (或 E_NOTICE) 是會讓 PHP 的 php_variables.c 程式繼續執行, 所以間接地牽涉的 Z_ARRVAL_PP

請多多指教。

謝謝
George</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/03/29/1949.html"  rel="bookmark"  title="Permanent Link: 深入理解PHP原理之Session Gc的一个小概率Notice" >深入理解PHP原理之Session Gc的一个小概率Notice</a></li><li><a href="http://www.laruence.com/2008/09/20/523.html"  rel="bookmark"  title="Permanent Link: PHP5.3 α2初体验" >PHP5.3 α2初体验</a></li><li><a href="http://www.laruence.com/2011/07/02/2097.html"  rel="bookmark"  title="Permanent Link: PHP5.4的新特性" >PHP5.4的新特性</a></li><li><a href="http://www.laruence.com/2011/10/10/2232.html"  rel="bookmark"  title="Permanent Link: 二进制直接量(binary number format)" >二进制直接量(binary number format)</a></li><li><a href="http://www.laruence.com/2011/12/19/2409.html"  rel="bookmark"  title="Permanent Link: 之前提到的PHP5.4一个注意点的update" >之前提到的PHP5.4一个注意点的update</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li><li><a href="http://www.laruence.com/2011/11/09/2277.html"  title="PHP原理之内存管理中难懂的几个点" >PHP原理之内存管理中难懂的几个点</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/12/30/2440.html/feed</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>PHP数组的Hash冲突实例</title>
		<link>http://www.laruence.com/2011/12/30/2435.html</link>
		<comments>http://www.laruence.com/2011/12/30/2435.html#comments</comments>
		<pubDate>Fri, 30 Dec 2011 06:30:46 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[转载]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[Hash collision]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[性能]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2435</guid>
		<description><![CDATA[   上一篇文章, 我介绍了一个<a href="http://www.laruence.com/2011/12/29/2412.html">利用Hash冲突(碰撞)来对各种语言(包括,PHP, Java, Ruby等等)实施拒绝服务攻击的可能</a>,  但是没有给出实例,  文章发出后, @Ferrari同学给出了一个另外一篇文章<a href="http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html">Supercolliding a PHP array</a>, 文章中作者介绍了一种基于PHP的冲突实例, 以及带来的性能恶化对比. 我就借花献佛, 翻译给大家看看.

    你知道不知道, 插入65536个经过构造的键值的元素到PHP数组, 会需要耗时30秒以上?  而一般的这个过程仅仅需要0.1秒..]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2011/12/30/2435.html"  title="Permanet Link to PHP数组的Hash冲突实例" >http://www.laruence.com/2011/12/30/2435.html</a></li>
<li>文章转自: <a href="http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html" >Supercolliding a PHP array</a></li>
</ul></div>
<p>
    上一篇文章, 我介绍了一个<a href="http://www.laruence.com/2011/12/29/2412.html" >利用Hash冲突(碰撞)来对各种语言(包括,PHP, Java, Ruby等等)实施拒绝服务攻击的可能</a>,  但是没有给出实例,  文章发出后, @Ferrari同学给出了一个另外一篇文章<a href="http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html" >Supercolliding a PHP array</a>, 文章中作者介绍了一种基于PHP的冲突实例, 以及带来的性能恶化对比. 我就借花献佛, 翻译给大家看看.</p>
<p>    你知道不知道, 插入65536个经过构造的键值的元素到PHP数组, 会需要耗时30秒以上?  而一般的这个过程仅仅需要0.1秒..</p>
<p>    请看如下的例子:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
$size = pow(2, 16); 

$startTime = microtime(true);
$array = array();
for ($key = 0, $maxKey = ($size - 1) * $size; $key &lt;= $maxKey; $key += $size) {
    $array[$key] = 0;
}
$endTime = microtime(true);
echo '插入 ', $size, ' 个恶意的元素需要 ', $endTime - $startTime, ' 秒', &quot;\n&quot;;

$startTime = microtime(true);
$array = array();
for ($key = 0, $maxKey = $size - 1; $key &lt;= $maxKey; ++$key) {
    $array[$key] = 0;
}
$endTime = microtime(true);
echo '插入 ', $size, ' 个普通元素需要 ', $endTime - $startTime, ' 秒', &quot;\n&quot;;
</pre>
<p>上面的例子, 在我的机器上的执行结果如下:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
插入 65536 个恶意的元素需要 43.1438360214 秒
插入 65536 个普通元素需要 0.0210378170013 秒
</pre>
<p>这个差别是不是很夸张?!</p>
<p>我在<a href="http://www.laruence.com/2011/12/29/2412.html" >上一篇文章中</a>介绍过,  经过特殊构造的键值,  使得PHP每一次插入都会造成Hash冲突, 从而使得PHP中array的底层Hash表退化成链表:<br/>
<div id="attachment_2415"  class="wp-caption aligncenter"  style="width: 618px" ><a href="http://laruence-wordpress.stor.sinaapp.com/uploads/Untitled3.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/Untitled3.png"  alt=""  title="Hash collision"  width="608"  height="223"  class="size-full wp-image-2415" /></a><p class="wp-caption-text" >Hash collision</p></div><br/>
这样在每次插入的时候PHP都需要遍历一遍这个链表, 大家可以想象,  第一次插入, 需要遍历0个元素, 第二次是1个, 第三次是3个, 第65536个是65535个, 那么总共就需要65534*65535/2=2147385345次遍历&#8230;.</p>
<p>那么, 这个键值是怎么构造的呢?</p>
<p>在PHP中,如果键值是数字, 那么Hash的时候就是数字本身,  一般的时候都是, index &#038; tableMask.  而tableMask是用来保证数字索引不会超出数组可容纳的元素个数值, 也就是数组个数-1.</p>
<p>PHP的Hashtable的大小都是2的指数, 比如如果你存入10个元素的数组, 那么数组实际大小是16, 如果存入20个, 则实际大小为32,   而63个话, 实际大小为64.  当你的存入的元素个数大于了数组目前的最多元素个数的时候, PHP会对这个数组进行扩容, 并且从新Hash.</p>
<p>现在,  我们假设要存入64个元素(中间可能会经过扩容, 但是我们只需要知道, 最后的数组大小是64, 并且对应的tableMask为63:0111111),  那么如果第一次我们存入的元素的键值为0,  则hash后的值为0,  第二次我们存入64, hash(1000000 &#038; 0111111)的值也为0, 第三次我们用128, 第四次用192&#8230; 就可以使得底层的PHP数组把所有的元素都Hash到0号bucket上, 从而使得Hash表退化成链表了.</p>
<p>当然, 如果键值是字符串的话, 就稍微比较麻烦一些了, 但是PHP的<a href="http://www.laruence.com/2009/07/23/994.html" >Hash算法</a>是开源的, 已知的, 所以有心人也可以做到&#8230;<br/>
<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/30</a>, <a href="http://kimbs.cn"  rel="external nofollow"  class="url" >kim</a> writes: 沙发！
简单地说就是，通过构造一个 url ，或者一个 form ，参数的 key 就按这么 $key += $size 计算，那么就能拖慢所有使用存在此缺陷的 server ~，oh my god.</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/30</a>, mahone writes: 灰常不错，受教了。。。</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/30</a>, mahone writes: 刚测试了下，发现个问题，请教下
在我本地虚拟机（32位ubuntu系统，512m内存，1核cpu，2.66GHz）上跑上面的程序：
插入 65536 个恶意的元素需要 90.800883054733 秒
插入 65536 个普通元素需要 0.026834011077881 秒
服务器（64位系统，2g内存，4核1.60GHz）上跑：
插入 65536 个恶意的元素需要 190.03647112846 秒
插入 65536 个普通元素需要 0.027021884918213 秒

这个差距是因为cpu频率的关系？php能利用多核的优势么？还是因为系统是32位或者64位的关系？</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/30</a>, <a href="http://www.laruence.com/2011/12/30/2440.html"  rel="external nofollow"  class="url" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch | 风雪之隅</a> writes: [...] PHP数组的Hash冲突实例  ), 这个攻击方法危害很高, 攻击成本也很小. [...]</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/30</a>, <a href="http://hjin.me"  rel="external nofollow"  class="url" >HJin_me</a> writes: 鸟哥，你的半官方补丁能发布出来么～～对很多人来说，非稳定版本的不敢用啊。</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/30</a>, <a href="http://blog.biaojita.com"  rel="external nofollow"  class="url" >dk</a> writes: 控制一下GPC三个超全局变量的解析时间是否就解决了潜在的DDOS攻击呢？</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/30</a>, <a href="http://www.xingdonghai.cn/a-new-supercolliding-with-array-of-php/"  rel="external nofollow"  class="url" >关于最近PHP的Array爆出的冲突问题 | 东海博客</a> writes: [...] 详细内容：http://www.laruence.com/2011/12/30/2435.html [...]</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/31</a>, <a href="http://blog.csdn.net/linvo"  rel="external nofollow"  class="url" >linvo</a> writes: 请教鸟哥，有一点我还是不太明白，$size=pow(2, n)中n取值的缘由？
我把代码做了一些修改后测试发现，当n取值为14~18的时候，效果最好。大于或小于的话，速度都会明显变快。</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2011/12/31</a>, wow writes: [root@WangXJ php_test]# time  php f.php 
插入 65536 个普通元素需要  0.053505897521973 sec

real	0m0.086s
user	0m0.080s
sys	0m0.004s

大神 我想请教下 为什么time 命令统计的时间real time会大于php自己统计的时间呢</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2012/01/06</a>, a writes: 请问，怎么用这个BUG攻击你的blog？挺起来好象这BUG很厉害的样子。</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2012/01/07</a>, <a href="http://blog.jobbole.com/11516/"  rel="external nofollow"  class="url" >PHP哈希表碰撞攻击原理 - 博客 - 伯乐在线</a> writes: [...] [4] PHP数组的Hash冲突实例 [...]</li><li><a href="http://www.laruence.com/2011/12/30/2435.html" >2012/01/11</a>, <a href="http://ok"  rel="external nofollow"  class="url" >jimmyyem</a> writes: 看了好久，为了一些人才看明白，很受教</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/07/23/994.html"  rel="bookmark"  title="Permanent Link: PHP中的Hash算法" >PHP中的Hash算法</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/10/15/1131.html"  title="提升PHP性能之改变Zend引擎分发方式" >提升PHP性能之改变Zend引擎分发方式</a></li><li><a href="http://www.laruence.com/2009/07/23/994.html"  title="PHP中的Hash算法" >PHP中的Hash算法</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/12/30/2435.html/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>通过构造Hash冲突实现各种语言的拒绝服务攻击</title>
		<link>http://www.laruence.com/2011/12/29/2412.html</link>
		<comments>http://www.laruence.com/2011/12/29/2412.html#comments</comments>
		<pubDate>Thu, 29 Dec 2011 04:31:12 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Ddos]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[max_input_vars]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[V8]]></category>
		<category><![CDATA[漏洞]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2412</guid>
		<description><![CDATA[   上周的时候Dmitry突然在5.4发布在即的时候, 引入了一个新的配置项:
<coolcode lang="php" linenum="off">
Added max_input_vars directive to prevent attacks based on hash collisions
</coolcode>

   这个预防的攻击, 就是"通过调用Hash冲突实现各种语言的拒绝服务攻击漏洞"(multiple implementations denial-of-service via hash algorithm collision).
]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/12/29/2412.html"  title="Permanet Link to 通过构造Hash冲突实现各种语言的拒绝服务攻击" >http://www.laruence.com/2011/12/29/2412.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   上周的时候Dmitry突然在5.4发布在即的时候, 引入了一个新的配置项:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
Added max_input_vars directive to prevent attacks based on hash collisions
</pre>
<p>   这个预防的攻击, 就是&#8221;通过调用Hash冲突实现各种语言的拒绝服务攻击漏洞&#8221;(multiple implementations denial-of-service via hash algorithm collision).</p>
<p>   攻击的原理很简单, 目前很多语言, 使用hash来存储k-v数据, 包括常用的来自用户的POST数据, 攻击者可以通过构造请求头, 并伴随POST大量的特殊的&#8221;k&#8221;值(根据每个语言的Hash算法不同而定制), 使得语言底层保存POST数据的Hash表因为&#8221;冲突&#8221;(碰撞)而退化成链表.<br/>
<a href="http://laruence-wordpress.stor.sinaapp.com/uploads/Untitled3.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/Untitled3.png"  alt=""  title="Hash collision"  width="608"  height="223"  class="aligncenter size-full wp-image-2415" /></a></p>
<p>   这样一来, 如果数据量<b>足够大</b>, 那么就可以使得语言在计算, 查找, 插入的时候, 造成大量的CPU占用, 从而实现拒绝服务攻击. </p>
<p>   PHP5.4是通过增加一个限制来尽量避免被此类攻击影响:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
  - max_input_vars - specifies how many GET/POST/COOKIE input variables may be
    accepted. default value 1000.
</pre>
</p>
<p><b> 目前已知的受影响的语言以及版本有:</b>:</p>
<p><a href="http://www.java.com" >Java</a>, 所有版本</p>
<p><a href="http://jruby.org/" >JRuby</a> &lt;= 1.6.5</p>
<p><a href="http://www.php.net/" >PHP</a> &lt;= 5.3.8, &lt;= 5.4.0RC3</p>
<p><a href="http://python.org/" >Python</a>, 所有版本</p>
<p><a href="http://rubini.us/" >Rubinius</a>, 所有版本</p>
<p><a href="http://www.ruby-lang.org/" >Ruby</a> &lt;= 1.8.7-p356</p>
<p><a href="http://geronimo.apache.org/" >Apache Geronimo</a>, 所有版本</p>
<p><a href="http://tomcat.apache.org/" >Apache Tomcat</a> &lt;= 5.5.34, &lt;= 6.0.34, &lt;= 7.0.22</p>
<p><a href="http://glassfish.java.net/" >Oracle Glassfish</a> &lt;= 3.1.1</p>
<p><a href="http://www.eclipse.org/jetty/" >Jetty</a>, 所有版本</p>
<p><a href="http://plone.org/" >Plone</a>, 所有版本</p>
<p><a href="http://rack.rubyforge.org/" >Rack</a>, 所有版本</p>
<p><a href="http://code.google.com/p/v8/" >V8 JavaScript Engine</a>, 所有版本</p>
<p><b>不受此影响的语言或者修复版本的语言有:</b>:</p>
<p><a href="http://www.php.net/" >PHP</a> &gt;= 5.3.9, &gt;= 5.4.0RC4</p>
<p><a href="http://jruby.org/" >JRuby</a> &gt;= 1.6.5.1</p>
<p><a href="http://www.ruby-lang.org/" >Ruby</a> &gt;= 1.8.7-p357, 1.9.x</p>
<p><a href="http://tomcat.apache.org/" >Apache Tomcat</a> &gt;= 5.5.35, &gt;= 6.0.35, &gt;= 7.0.23</p>
<p><a href="http://glassfish.java.net/" >Oracle Glassfish</a>, N/A (Oracle reports that the issue is fixed in the main codeline and scheduled for a future CPU)</p>
<p><b>CVE</b>:  <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4885" >CVE-2011-4885</a> (PHP),  <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4885" >CVE-2011-4461</a> (Jetty),  <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4838" >CVE-2011-4838</a> (JRuby),  <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4885" >CVE-2011-4462</a> (Plone),  <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4815" >CVE-2011-4815</a> (Ruby)
</p>
<p>    原文: <a href="http://www.ocert.org/advisories/ocert-2011-003.html" >http://www.ocert.org/advisories/ocert-2011-003.html</a><br/>
   <script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/29</a>, <a href="http://blog.csdn.net/sunvince"  rel="external nofollow"  class="url" >sunvince</a> writes: 好想法...</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/29</a>, aries writes: 这个，现在有可行的方法来构造大量hash值相同的不同原文？</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, Ferrari writes: 請問這篇的作者解釋的是同一個問題嗎?
http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, <a href="http://xiezhenye.com/"  rel="external nofollow"  class="url" >神仙</a> writes: 如果是用的rbtree之类就不会有这麻烦了吧</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @Ferrari 恩,是一样的事情, :)</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, <a href="http://www.laruence.com/2011/12/30/2435.html"  rel="external nofollow"  class="url" >PHP数组的Hash冲突实例 | 风雪之隅</a> writes: [...]  [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, <a href="http://kimbs.cn"  rel="external nofollow"  class="url" >kim</a> writes: 这不是基本上全部中招？</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, mahone writes: max_input_vars - specifies how many GET/POST/COOKIE input variables may be
    accepted. default value 1000.

这个1000，是get,post,cookie这种加起来一共1000？还是get1000，post1000，cookie1000？</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, jw writes: hi,niaoge
为啥不在每个bucket中加个指针指向链表结尾来解决问题，而是采用限制输入长度的方案
thx</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, <a href="http://www.laruence.com/2011/12/30/2440.html"  rel="external nofollow"  class="url" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch | 风雪之隅</a> writes: [...] Posts:PHP数组的Hash冲突实例通过构造Hash冲突实现各种语言的拒绝服务攻击更简单的重现PHP Core的调用栈GBK编码PHP脚本导致语法错误(Zend [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, <a href="http://www.xiuwz.com/site/news-hash-ph-java-ddos/"  rel="external nofollow"  class="url" >高危安全：Hash冲突导致PHP/JAVA/PYTHON等DDOS攻击 | 网站那些事 | 网站点兵</a> writes: [...] 高危安全：Hash冲突导致PHP/JAVA/PYTHON等DDOS攻击   作者: xiuwz 日期: 2011 年 12 月 30 日  发表评论 (0) 查看评论   (No Ratings Yet) &nbsp;Loading ...     分享到：     更多    国外目前报出“multiple implementations denial-of-service via hash algorithm collision”，该hash冲突漏洞对目前所有的WEB动态开发语言都有危害，导致一个用户可以轻松通过构造数据而造成任何网站拒绝服务，从而引发DDOS相关攻击。中文版介绍请参考http://www.laruence.com/2011/12/29/2412.html。 [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/30</a>, <a href="http://www.xingdonghai.cn/a-new-supercolliding-with-array-of-php/"  rel="external nofollow"  class="url" >关于最近PHP的Array爆出的冲突问题 | 东海博客</a> writes: [...] 原理（详见：http://www.laruence.com/2011/12/29/2412.html） [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/31</a>, <a href="http://dabai.org/life/2011/12/php-array-hash-collisions/"  rel="external nofollow"  class="url" >PHP数组特殊Hash冲突问题</a> writes: [...] 通过构造Hash冲突实现各种语言的拒绝服务攻击 PHP数组的Hash冲突实例 深入理解PHP之数组(遍历顺序) Supercolliding a PHP array 哈希表(HashTable) PHP的哈希表实现    &nbsp;           If you enjoyed this article, please consider sharing it! [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2011/12/31</a>, <a href="http://blog.qijur.com/?p=88"  rel="external nofollow"  class="url" >Hash表碰撞导致dos攻击 | 亿光年</a> writes: [...] http://www.laruence.com/2011/12/29/2412.html [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/02</a>, <a href="http://upsuper.org/"  rel="external nofollow"  class="url" >upsuper</a> writes: Python 似乎受影响不大，首先 Python 本身不解析大量外部数据，所以不存在类似 PHP 那样针对语言层面的攻击，过滤过多参数只需要相关框架增加选项即可。其次 Python 的 Hash 算法似乎并不容易用来大规模构造冲撞数据，构造难度跟纯枚举差不多，所以短期内被攻击的可能性不大。</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/02</a>, yc2266 writes: 这个问题 百度可以共享一下 hi 空间里面的博文链接key 计算方式：

http://hi.baidu.com/baidu/blog/item/b95bb39997ebc2166f068cec.html

b95bb39997ebc2166f068cec 这个key的计算方式能保证在多少范围内不产生碰撞！(具体多少我也不知道)保证这个算法在一定范围的稳定性！</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/03</a>, <a href="http://www.tanglei.name"  rel="external nofollow"  class="url" >tanglei</a> writes: 这个，java怎么中招啊？
求解释。
java中的数组不会支持很大，受内存限制吧。
不过在hashmap中，有类似的影响。不过相差不大。</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/04</a>, <a href="https://larryli.cn/2012/01/644577"  rel="external nofollow"  class="url" >Suhosin, Good job! | 南靖男的时代</a> writes: [...] 年末传出动态语言大范围的 Hash DOS [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/04</a>, <a href="http://&#039;"  rel="external nofollow"  class="url" >'</a> writes: '</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/04</a>, hoho writes: alert('test')</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/05</a>, <a href="http://www.unclejoey.com"  rel="external nofollow"  class="url" >Joey Yin</a> writes: JAVA下hash冲突生成代码请参考：http://www.unclejoey.com/?p=554</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/05</a>, <a href="http://www.openews.net/2012/kangle-2-7-5-emergency-release-anti-collision-attacks-on-hash/"  rel="external nofollow"  class="url" >kangle 2.7.5 emergency release, anti-collision attacks on hash - Open News</a> writes: [...] collision theory:  http://www.laruence.com/2011/12/29/2412.html  [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/05</a>, <a href="http://summerbluet.com/post/533"  rel="external nofollow"  class="url" >通过调用Hash冲突实现各种语言的拒绝服务攻击漏洞 | Charlie&#039;s Coffee House</a> writes: [...] Laruence 的翻疑问 [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/06</a>, <a href="http://www.lnmpblog.com"  rel="external nofollow"  class="url" >fare</a> writes: 彻底的修改方法，就是改一下hash函数，在编译安装的时候，自动生成一个随机的p,hash的时候带上这个p，就很难构造退化的链表了。</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/07</a>, <a href="http://www.osmax.info/2012/01/350.osmax"  rel="external nofollow"  class="url" >kangle 2.7.5 紧急发布,防hash碰撞攻击 | 草石网</a> writes: [...] hash碰撞原理: http://www.laruence.com/2011/12/29/2412.html [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/07</a>, <a href="http://blog.yuaz.net/archives/244"  rel="external nofollow"  class="url" >Ruby和Rack解决因Hash表碰撞导致CPU拒绝服务的Bug &#8211; Imagine::Blog.new</a> writes: [...] 前几天，各个主流语言都爆出来了大Bug：“通过调用Hash冲突实现各种语言的拒绝服务攻击漏洞”（multiple implementations denial-of-service via hash algorithm collisio）。《通过构造Hash冲突实现各种语言的拒绝服务攻击》这篇文章提到PHP里引入了新的配置项，来限制GET/POST/COOKIE输入变量来减少攻击的影响。 [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/08</a>, <a href="http://www.tanglei.name/use-hash-collision-to-realize-dos-in-php-and-java/"  rel="external nofollow"  class="url" >通过构造Hash冲突实现PHP/Java等语言的拒绝服务攻击 &raquo; tanglei&#039;s blog 唐磊的个人博客</a> writes: [...] 前几天看到公司php群谈到这篇博文通过构造Hash冲突实现各种语言的拒绝服务攻击,说的是在PHP中，使用hash来存储k-v数据, 包括常用的来自用户的POST数据, 攻击者可以通过构造请求头, 并伴随POST大量的特殊的”k”值(根据每个语言的Hash算法不同而定制), 使得语言底层保存POST数据的Hash表因为”冲突”(碰撞)而退化成链表. 这样一来, 如果数据量足够大, 那么就可以使得语言在计算, 查找, 插入的时候, 造成大量的CPU占用, 从而实现拒绝服务攻击. 举个例子：如下代码中： 123456789101112131415161718192021222324252627&lt;?php  $size = pow&#040;2, 16&#041;; // 16 is just an example, could also be 15 or 17  $startTime = microtime&#040;true&#041;;  $array = array&#040;&#041;; for &#040;$key = 0, $maxKey = &#040;$size - 1&#041; * $size; $key &lt;= $maxKey; $key += $size&#041; &#123; &nbsp; &nbsp; &nbsp; &nbsp; $array&#091;$key&#093; = 0; &#125;  $endTime = microtime&#040;true&#041;;  echo &#039;Inserting &#039;, $size, &#039; evil elements took &#039;, $endTime - $startTime, &#039; seconds&#039;, &quot;n&quot;;  $startTime = microtime&#040;true&#041;;  $array = array&#040;&#041;; for &#040;$key = 0, $maxKey = $size - 1; $key &lt;= $maxKey; ++$key&#041; &#123; &nbsp; &nbsp; &nbsp; &nbsp; $array&#091;$key&#093; = 0; &#125;  $endTime = microtime&#040;true&#041;;  echo &#039;Inserting &#039;, $size, &#039; good elements took &#039;, $endTime - $startTime, &#039; seconds&#039;, &quot;n&quot;; //http://www.laruence.com/2011/12/30/2435.html ?&gt; [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/11</a>, <a href="http://www.zhouming.me/2012/01/wordpress-and-php-updated/"  rel="external nofollow"  class="url" >WordPress 升级到3.3.1，PHP升级到5.3.9，推荐DiffMerge | Ming&#039;s Blog</a> writes: [...] PHP版本升级到5.3.9，建议没有升级的赶快升级，防止受到Hash冲突拒绝服务攻击，可以参考 http://www.laruence.com/2011/12/29/2412.html，不过这么小的个人站点应该没有人有兴趣攻击。 [...]</li><li><a href="http://www.laruence.com/2011/12/29/2412.html" >2012/01/16</a>, <a href="http://www.nginxidc.com/kangle-hash/"  rel="external nofollow"  class="url" >kangle 2.7.5轻松防hash碰撞 &laquo; NginxIDC</a> writes: [...] hash碰撞原理: http://www.laruence.com/2011/12/29/2412.html [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2008/07/24/206.html"  title="Apache启动过程(PHP_MINIT_FUNCTION的调用)" >Apache启动过程(PHP_MINIT_FUNCTION的调用)</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/12/29/2412.html/feed</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>更简单的重现PHP Core的调用栈</title>
		<link>http://www.laruence.com/2011/12/06/2381.html</link>
		<comments>http://www.laruence.com/2011/12/06/2381.html#comments</comments>
		<pubDate>Tue, 06 Dec 2011 13:04:53 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[core]]></category>
		<category><![CDATA[coredump]]></category>
		<category><![CDATA[gdb]]></category>
		<category><![CDATA[gdbinit]]></category>
		<category><![CDATA[how to gdb a php core]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP5.4新特性]]></category>
		<category><![CDATA[segment fault]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2381</guid>
		<description><![CDATA[以前, 我曾经介绍过如何通过PHP的Core文件获取信息:<a href="http://www.laruence.com/2011/06/23/2057.html">如何调试PHP的Core之获取基本信息</a>, 对于调用参数这块, 当时介绍的获取方法比较复杂.

   于是今天我为PHP 5.4的.gdbinit做了一个改进, 以后如果你遇到了PHP 5.4的core, 那么就可以简单的得到PHP 5.4发生Core时, 包括参数的函数调用栈的信息.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/12/06/2381.html"  title="Permanet Link to 更简单的重现PHP Core的调用栈" >http://www.laruence.com/2011/12/06/2381.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    以前, 我曾经介绍过如何通过PHP的Core文件获取信息:<a href="http://www.laruence.com/2011/06/23/2057.html" >如何调试PHP的Core之获取基本信息</a>, 对于调用参数这块, 当时介绍的获取方法比较复杂.</p>
<p>   于是今天我为PHP 5.4的.gdbinit做了一个改进, 以后如果你遇到了PHP 5.4的core, 那么就可以简单的得到PHP 5.4发生Core时, 包括参数的函数调用栈的信息.</p>
<p>    假设对于如下的脚本:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php

class Test {
}

function a($i) {
    b(new Test, 2.3432, &quot;reader&quot;);
}
function b($i) {
    c(array(1,2,3));
}
function c($i) {
    d(TRUE);
}
function d($i) {
    $fp = fopen(&quot;/tmp/1.php&quot;, &quot;r&quot;);
    e($fp);
}

function e($i) {
    sleep(1000);
}

a();
</pre>
<p>    使用后台运行以后, PHP5.4会sleep在e函数的sleep中,  这时, 如果我们使用gdb attach上去, </p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
gdb --pid= xxx //使用ps获得后台运行脚本的pid
</pre>
<p>   然后, source  PHP源代码下面的.gdbinit:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
(gdb) source php54-src/.gdbinit
</pre>
<p>  然后,  让我们尝试调用下zbacktrace, 看看什么结果:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
(gdb) zbacktrace
[0x2a95dac5e0] sleep(1000) /tmp/1.php:21
[0x2a95dac4c0] e(resource(#5)) /tmp/1.php:17
[0x2a95dac3f0] d(true) /tmp/1.php:13
[0x2a95dac300] c(array(3)[0x2a95de7db0]) /tmp/1.php:10
[0x2a95dac1c0] b(object[0x2a95de7840], 2.343200, &quot;reader&quot;) /tmp/1.php:7
[0x2a95dac0e8] a() /tmp/1.php:24
</pre>
<p>    恩, 对于array和object, 因为我们为了保持不要乱屏, 所以没有展开, 不过, 如果我们要查看这个array具体是什么元素, 可以这样做, 注意到上面的:array(3)[0x2a95de7db0]:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
(gdb) print ((zval *)0x2a95de7db0)
$4 = (struct _zval_struct *) 0x2a95de7db0
(gdb) printzv $4
[0x2a95de7db0] (refcount=2) array(3): {
    0 =&gt; [0x2a95de79d0] (refcount=1) long: 1
    1 =&gt; [0x2a95de7b80] (refcount=1) long: 2
    2 =&gt; [0x2a95de7c98] (refcount=1) long: 3
  }
</pre>
<p>类似的, 对于object, 注意到上面的: object[0x2a95de7840]</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
(gdb) print ((zval *)0x2a95de7840)
$5 = (struct _zval_struct *) 0x2a95de7840
(gdb) printzv $5
[0x2a95de7840] (refcount=2) object
(Test) #1&quot;no properties found&quot;
</pre>
<p>    要注意的一点是, 对于object,  如果你是在调式Core文件, 而不是attach到一个运行的进程上, 那么上面的尝试会得到一个错误:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
(gdb) printzv $5
[0x2a95de7840] (refcount=2) objectYou can't do that without a process to debug.
</pre>
<p>    不过, 即使这样, 我们还是有办法, 只不过就比较麻烦了.在NTS下面:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
(gdb) p ((zval *)0x2a95de7840)-&gt;value.obj.handle
$6 = 1
//注意, 下面用到了这个$6的值:1
(gdb)  p (zend_object*) executor_globals-&gt;objects_store.object_buckets[1].bucket.obj.object
$7 = (struct _zend_object *) 0x2a95de3ec0
(gdb)  p $9-&gt;ce-&gt;name
$8 = 0x2a95e200b0 &quot;Test&quot;
</pre>
<p>    呵呵, 怎么样, 有了这些信息, 分析Core的原因, 是不是就更简单了呢?   enjoy~</p>
<p>    最后, 还是要提醒下: PHP 5.4还处于开发阶段, 在最终release之前, 任何新特性都可能被调整或者更改. 如果大家有任何建议, 也欢迎反馈, 帮助我们使得PHP变得更好.</p>
<p>    谢谢</p>
<p>    更多更新信息, 请关注: <a href="http://svn.php.net/viewvc/php/php-src/branches/PHP_5_4/NEWS?view=markup"  target="_blank" >Changelog</a><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/06</a>, 66beta writes: 完全看不懂，但是感觉很厉害的样子</li><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/06</a>, <a href="http://www.freefcw.info"  rel="external nofollow"  class="url" >巫山霏云</a> writes: 依然还是蛮麻烦的，不过确实要方便一些
不过要PHP CORE还真蛮难的</li><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/06</a>, <a href="http://www.shibeike.net"  rel="external nofollow"  class="url" >treesky</a> writes: 完全看不懂，但是感觉很厉害的样。Php，我才刚上路啊！</li><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/06</a>, <a href="http://www.cnxct.com"  rel="external nofollow"  class="url" >CFC4N</a> writes: 比起上一篇提到的isset的消息，这是个天大的好事情，调试代码性能简直方便多了，很容易找到执行最耗时的瓶颈所在。感谢PHP开发组。感谢鸟哥，感谢郭嘉。
PS：唠叨一遍，这是个好功能。</li><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/07</a>, xq262144 writes: 嗯，这个要好用多了，有参数的各种信息，不过我还是纠结于看HashTable的东西要人工计算hash。。。:-)</li><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/08</a>, chenchaogang writes: 打印那个object还是很不方便啊</li><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/10</a>, <a href="http://blog.iterse.com"  rel="external nofollow"  class="url" >Iterse's blog</a> writes: c的源码看不明白...</li><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/15</a>, Nathan writes: 能否写一篇详解apc参数的文章？官方的太简略了，部分参数完全不知道是干什么用的</li><li><a href="http://www.laruence.com/2011/12/06/2381.html" >2011/12/18</a>, pytonic writes: 可否给5.2.* 5.3.*加上此功能？
要用上5.4还要很久呢</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/10/26/1768.html"  rel="bookmark"  title="Permanent Link: AllowEncodedSlashes in Apache" >AllowEncodedSlashes in Apache</a></li><li><a href="http://www.laruence.com/2008/08/14/250.html"  rel="bookmark"  title="Permanent Link: 实现PHP的编译执行分离(separating compilation and execution)" >实现PHP的编译执行分离(separating compilation and execution)</a></li><li><a href="http://www.laruence.com/2011/10/19/2247.html"  rel="bookmark"  title="Permanent Link: Zend Signal in PHP 5.4" >Zend Signal in PHP 5.4</a></li><li><a href="http://www.laruence.com/2009/07/19/1003.html"  rel="bookmark"  title="Permanent Link: 使用gettext来支持PHP的多语言" >使用gettext来支持PHP的多语言</a></li><li><a href="http://www.laruence.com/2011/06/23/2057.html"  rel="bookmark"  title="Permanent Link: 如何调试PHP的Core之获取基本信息" >如何调试PHP的Core之获取基本信息</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/06/23/2057.html"  title="如何调试PHP的Core之获取基本信息" >如何调试PHP的Core之获取基本信息</a></li><li><a href="http://www.laruence.com/2011/10/10/2204.html"  title="JsonSerializable接口" >JsonSerializable接口</a></li><li><a href="http://www.laruence.com/2011/09/23/2171.html"  title="我对PHP5.4的一个改进" >我对PHP5.4的一个改进</a></li><li><a href="http://www.laruence.com/2011/07/14/2115.html"  title="Zend引擎的优化" >Zend引擎的优化</a></li><li><a href="http://www.laruence.com/2011/01/27/1854.html"  title="深入理解PHP内存管理之一个低概率Core的分析" >深入理解PHP内存管理之一个低概率Core的分析</a></li><li><a href="http://www.laruence.com/2010/09/27/1754.html"  title="PHP stream未能及时清理现场导致Core的bug" >PHP stream未能及时清理现场导致Core的bug</a></li><li><a href="http://www.laruence.com/2009/12/05/1172.html"  title="PHP5.2.x + APC的一个bug的定位" >PHP5.2.x + APC的一个bug的定位</a></li><li><a href="http://www.laruence.com/2008/12/31/647.html"  title="一个低概率的PHP Core dump" >一个低概率的PHP Core dump</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/12/06/2381.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>GBK编码PHP脚本导致语法错误(Zend Multibyte)</title>
		<link>http://www.laruence.com/2011/11/18/2305.html</link>
		<comments>http://www.laruence.com/2011/11/18/2305.html#comments</comments>
		<pubDate>Fri, 18 Nov 2011 09:20:08 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[declare]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[gbk]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[zend multibyte]]></category>
		<category><![CDATA[编码转换]]></category>
		<category><![CDATA[语法错误]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2305</guid>
		<description><![CDATA[   <a href="http://weibo.com/laruence">微薄</a>上有同学问我:
<coolcode lang="bash" linenum="off"> 
     GBK环境下如下php代码：<?php echo("洪仁玕");?> 会引发php的语法错误，如何解决？
</coolcode>

   这个是因为, 在GBK环境下, "玕"的编码是"0xab 0x5c,  所以, 又是一个'5c'引发的问题..

   一般来说, 还是建议大家用unicode作为代码文件的字符集,  如果要使用GBK, 再主动转换下.  

   不过, 就问题说问题,  如果你的脚本非要GBK编码, 那怎么避免这个问题呢?]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/11/18/2305.html"  title="Permanet Link to GBK编码PHP脚本导致语法错误(Zend Multibyte)" >http://www.laruence.com/2011/11/18/2305.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   <a href="http://weibo.com/laruence" >微薄</a>上有同学问我:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
     GBK环境下如下php代码：&lt;?php echo(&quot;洪仁玕&quot;);?&gt; 会引发php的语法错误，如何解决？
</pre>
<p>   这个是因为, 在GBK环境下, &#8220;玕&#8221;的编码是&#8221;0xab 0x5c,  所以, 又是一个&#8217;5c&#8217;引发的问题..</p>
<p>   一般来说, 还是建议大家用unicode作为代码文件的字符集,  如果要使用GBK, 再主动转换下.  </p>
<p>   不过, 就问题说问题,  如果你的脚本非要GBK编码, 那怎么避免这个问题呢?</p>
<p>   从PHP5.3开始,  PHP引入了Zend Multibyte来支持多字符集编码.   对于上面的代码, 我们修改如下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
declare(encoding=&quot;cp936&quot;);
echo(&quot;洪仁玕&quot;);
?&gt;
</pre>
<p>    然后, 在php.ini中配置: </p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
mbstring.internal_encoding=cp936
</pre>
<p>  或者通过如下命令运行PHP:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$php  -dmbstring.internal_encoding=cp936 test.php
</pre>
<p>   这样, PHP就会以cp936编码方式来执行test.php了.   关于Zend Multibyte的更多信息请参看:<a href="http://serverfault.com/questions/145413/php-what-is-enable-zend-multibyte-configure-option-for" >PHP: what is &#8211;enable-zend-multibyte configure option for?</a>, <a href="http://php.net/manual/en/control-structures.declare.php" >PHP declare</a></p>
<p>    PS, 我在试验PHP5.4 RC1的时候,  发现了一个BUG,  PHP 5.4 不能正确的转换GBK编码到UTF8编码,  不过现在我已经修复. 大家如果遇到这个问题, 请关注马上要发布的PHP5.4 RC2即可..  谢谢<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/11/18/2305.html" >2011/11/18</a>, cute writes: mb_internal_encoding("CP936");</li><li><a href="http://www.laruence.com/2011/11/18/2305.html" >2011/11/19</a>, <a href="http://baidu.com"  rel="external nofollow"  class="url" >maifa</a> writes: 我很想听下，又 一个 5C？
又的解释。谢谢。</li><li><a href="http://www.laruence.com/2011/11/18/2305.html" >2011/11/19</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @maifa http://www.laruence.com/2010/04/12/1396.html</li><li><a href="http://www.laruence.com/2011/11/18/2305.html" >2011/11/23</a>, <a href="http://www.pztai.com"  rel="external nofollow"  class="url" >taylor</a> writes: 好诡异的bug啊
最近碰到个因为转码的原因导致$_GET失败的问题，好诡异，最后是因为前段给的链接给urlencode了,纠结</li><li><a href="http://www.laruence.com/2011/11/18/2305.html" >2011/11/23</a>, eve writes: 我觉得是不是可以先用记事本打开代码，然后另存为utf-8编码，这样问题就解决了.您觉得呢</li><li><a href="http://www.laruence.com/2011/11/18/2305.html" >2011/11/29</a>, <a href="http://www.zhaiduo.com"  rel="external nofollow"  class="url" >zhaiduo</a> writes: 我在用mysql_real_escape_string的时候也遇到5c问题，用mysql_escape_string就不会有5c问题。</li><li><a href="http://www.laruence.com/2011/11/18/2305.html" >2011/12/23</a>, <a href="http://ihacklog.com"  rel="external nofollow"  class="url" >荒野无灯</a> writes: 嗯，以前看过gbk字符集下mysql_escape函数的一个0x5c引起的bug~~</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2008/08/15/274.html"  rel="bookmark"  title="Permanent Link: PHP 源代码分析 V0.0.2" >PHP 源代码分析 V0.0.2</a></li><li><a href="http://www.laruence.com/2008/07/16/225.html"  rel="bookmark"  title="Permanent Link: Zend Engine幻想" >Zend Engine幻想</a></li><li><a href="http://www.laruence.com/2010/06/21/1608.html"  rel="bookmark"  title="Permanent Link: PHP调试技术手册发布(1.0.0 pdf)" >PHP调试技术手册发布(1.0.0 pdf)</a></li><li><a href="http://www.laruence.com/2011/10/10/2229.html"  rel="bookmark"  title="Permanent Link: 函数类型提示(Callable typehint)" >函数类型提示(Callable typehint)</a></li><li><a href="http://www.laruence.com/2011/10/19/2247.html"  rel="bookmark"  title="Permanent Link: Zend Signal in PHP 5.4" >Zend Signal in PHP 5.4</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/11/16/1147.html"  title="分割GBK中文遭遇乱码的解决" >分割GBK中文遭遇乱码的解决</a></li><li><a href="http://www.laruence.com/2009/05/31/889.html"  title="PHP受locale影响的函数" >PHP受locale影响的函数</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/11/18/2305.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>PHP原理之内存管理中难懂的几个点</title>
		<link>http://www.laruence.com/2011/11/09/2277.html</link>
		<comments>http://www.laruence.com/2011/11/09/2277.html#comments</comments>
		<pubDate>Wed, 09 Nov 2011 09:50:09 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[zend mm]]></category>
		<category><![CDATA[内存管理]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2277</guid>
		<description><![CDATA[     PHP的内存管理,  分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理.  而第二部分就是今天我要介绍的, zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等.

     另外, 为什么要写这个呢, 因为之前并没有任何资料来介绍PHP内存管理中使用的策略, 数据结构, 或者算法.  而在我们平时开发扩展, 修复PHP的bug的时候, 却对这一部分的知识需要有一个良好的理解. PHP开发组内的很多朋友也对这块不是很清楚, 所以我觉得有必要专门写一下.

     一些基本的概念, 我就不赘述了, 因为看代码很容易能看懂,  我这里就主要介绍几个看代码没那么容易看懂的点,  为什么这么说呢,  呵呵, 我在写文章之前, 查找了下已有的资料, 已避免重复功,  其中看到了TIPI项目对这部分的描述,  发现其中错误很多.  所以, 我想这部分就是看代码也没那么容易看懂的点 :)]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/11/09/2277.html"  title="Permanet Link to PHP原理之内存管理中难懂的几个点" >http://www.laruence.com/2011/11/09/2277.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
     PHP的内存管理,  分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理.  而第二部分就是今天我要介绍的, zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等.</p>
<p>     另外, 为什么要写这个呢, 因为之前并没有任何资料来介绍PHP内存管理中使用的策略, 数据结构, 或者算法.  而在我们平时开发扩展, 修复PHP的bug的时候, 却对这一部分的知识需要有一个良好的理解. PHP开发组内的很多朋友也对这块不是很清楚, 所以我觉得有必要专门写一下.</p>
<p>     一些基本的概念, 我就不赘述了, 因为看代码很容易能看懂,  我这里就主要介绍几个看代码没那么容易看懂的点,  为什么这么说呢,  呵呵, 我在写文章之前, 查找了下已有的资料, 已避免重复功,  其中看到了TIPI项目对这部分的描述,  发现其中错误很多.  所以, 我想这部分就是看代码也没那么容易看懂的点 <img src="http://www.laruence.com/wp-includes/images/smilies/icon_smile.gif"  alt=":)"  class="wp-smiley" /> </p>
<p>     目前, 英文版的介绍也在撰写中: <a href="https://wiki.php.net/internals/zend_mm" >Zend MM</a></p>
<p>     Zend Memory Manager, 以下简称Zend MM, 是PHP中内存管理的逻辑.  其中有一个关键数据结构: zend_mm_heap:<br/>
<a href="http://laruence-wordpress.stor.sinaapp.com/uploads/zend_mm.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/zend_mm.png"  alt=""  title="zend_mm"  width="597"  height="451"  class="aligncenter size-full wp-image-2278" /></a></p>
<p>     Zend MM把内存非为小块内存和大块内存俩种, 区别对待, 对于小块内存, 这部分是最最常用的, 所以追求高性能. 而对于大块内存, 则追求的是稳妥, 尽量避免内存浪费.</p>
<p>     所以, 对于小块内存, PHP还引入了cache机制:<br/>
<a href="http://laruence-wordpress.stor.sinaapp.com/uploads/zend_mm_cache.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/zend_mm_cache.png"  alt=""  title="zend_mm_cache"  width="521"  height="385"  class="aligncenter size-full wp-image-2284" /></a></p>
<p>     Zend MM 希望通过cache尽量做到, 一次定位就能查找分配.</p>
<p>     而一个不容易看懂的点是free_buckets的申明:</p>
<p>     Q: 为什么free_buckets数组的长度是ZEND_MM_NUMBER_BUCKET个? </p>
<p>     A: 这是因为, PHP在这处使用了一个技巧, 用一个定长的数组来存储ZEND_MM_NUMBER_BUCKET个zend_mm_free_block, 如上图中红色框所示.  对于一个没有被使用的free_buckets的元素, 唯一有用的数据结构就是next_free_block和prev_free_block, 所以, 为了节省内存, PHP并没有分配ZEND_MM_NUMBER_BUCKET * sizeof(zend_mm_free_block)大小的内存, 而只是用了ZEND_MM_NUMBER_BUCKET * (sizeof(*next_free_block) + sizeof(*prev_free_block))大小的内存..</p>
<p>    我们来看ZEND_MM_SMALL_FREE_BUCKET宏的定义:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
    (zend_mm_free_block*) ((char*)&amp;heap-&gt;free_buckets[index * 2] + \
        sizeof(zend_mm_free_block*) * 2 - \
        sizeof(zend_mm_small_free_block))
</pre>
<p>    之后, Zend MM 保证只会使用prev和next俩个指针, 所以不会造成内存读错..</p>
<p>    那么, 第二个不容易看懂的点, 就是PHP对large_free_buckets的管理, 先介绍分配(TIPI项目组对此部分的描述有些含糊不清):</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
static zend_mm_free_block *zend_mm_search_large_block(zend_mm_heap *heap, size_t true_size)
</pre>
<p>   large_free_buckets可以说是一个建树和双向列表的结合:<br/>
<a href="http://laruence-wordpress.stor.sinaapp.com/uploads/zend_mm_large_buckets1.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/zend_mm_large_buckets1.png"  alt=""  title="zend_mm_large_buckets"  class="aligncenter size-full wp-image-2292" /></a></p>
<p>   large_free_buckets使用一个宏来决定某个大小的内存, 落在什么index上:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S)
</pre>
<p>   zend_mm_high_bit获取true_size中最高位1的序号(zend_mm_high_bit), 对应的汇编指令是bsr(此处, TIPI项目错误的说明为: &#8220;这个hash函数用来计算size的位数，返回值为size二进码中1的个数-1&#8243;).</p>
<p>   也就是说, 每一个在large_free_buckets中的元素, 都保持着指向一个大小为在对应index处为1的size的内存块的指针.  诶, 有点绕口, 举个例子:</p>
<p>   比如对于large_free_buckets[2], 就只会保存, 大小在0b1000到0b1111大小的内存. 再比如: large_free_buckets[6], 就保存着大小为0b10000000到0b11111111大小的内存的指针.</p>
<p>   这样, 再分配内存的时候, Zend MM就可以快速定位到最可能适合的区域来查找. 提高性能.</p>
<p>   而, 每一个元素又同时是一个双向列表, 保持着同样size的内存块, 而左右孩子(child[0]和child[1])分别代表着键值0和1, 这个键值是指什么呢?</p>
<p>   我们来举个例子, 比如我向PHP申请一个true_size为0b11010大小的内存, 经过一番步骤以后, 没有找到合适的内存, PHP进入了zend_mm_search_large_block的逻辑来在large_free_buckets中寻找合适的内存:</p>
<p>1. 首先, 计算true_size对应的index,  计算方法如之前描述的ZEND_MM_LARGE_BUCKET_INDEX</p>
<p>2. 然后在一个位图结构中, 判断是否存在一个大于true_size的可用内存已经存在于large_free_buckets, 如果不存在就返回:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
size_t bitmap = heap-&gt;large_free_bitmap &gt;&gt; index;
if (bitmap == 0) {
   return NULL;
}
</pre>
<p>3. 判断, free_buckets[index]是否存在可用的内存:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
if (UNEXPECTED((bitmap &amp; 1) != 0))
</pre>
<p>4. 如果存在, 则从free_buckets[index]开始, 寻找最合适的内存, 步骤如下:</p>
<p>    4.1.  从free_buckets[index]开始,  如果free_buckets[index]当前的内存大小和true_size相等, 则寻找结束, 成功返回.</p>
<p>    4.2.  查看true_size对应index后(true_size << (ZEND_MM_NUM_BUCKETS - index))的当前最高位, 如果为1.  则在free_buckets[index]->child[1]下面继续寻找, 如果free_buckets[index]->child[1]不存在, 则跳出.  如果true_size的当前最高位为0, 则在free_buckets[index]->child[0]下面继续寻找, 如果free_buckets[index]->child[0]不存在, 则在free_buckets[index]->child[1]下面寻找最小内存(因为此时可以保证, 在free_buckets[index]->child[1]下面的内存都是大于true_size的)</p>
<p>    4.3. 出发点变更为2中所述的child, 左移一位ture_size. </p>
<p>5. 如果上述逻辑并没有找到合适的内存, 则寻找最小的&#8221;大块内存&#8221;:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
   /* Search for smallest &quot;large&quot; free block */
    best_fit = p = heap-&gt;large_free_buckets[index + zend_mm_low_bit(bitmap)];
    while ((p = p-&gt;child[p-&gt;child[0] != NULL])) {
        if (ZEND_MM_FREE_BLOCK_SIZE(p) &lt; ZEND_MM_FREE_BLOCK_SIZE(best_fit)) {
            best_fit = p;
        }
    }
</pre>
<p>注意上面的逻辑,  (p = p->child[p->child[0] != NULL]), PHP在尽量寻找最小的内存.</p>
<p>为什么说, large_free_buckets是个键树呢,  从上面的逻辑我们可以看出, PHP把一个size, 按照二进制的0,1做键, 把内存大小信息反应到了键树上, 方便了快速查找.</p>
<p>另外, 还有一个rest_buckets,  这个结构是个双向列表,  用来保存一些PHP分配后剩下的内存, 避免无意义的把剩余内存插入free_buckets带来的性能问题(此处, TIPI项目错误的描述为: &#8220;这是一个只有两个元素的数组。 而我们常用的插入和查找操作是针对第一个元素，即heap->rest_buckets[0]&#8220;).<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/11/09/2277.html" >2011/11/09</a>, <a href="http://weibo.com/walu"  rel="external nofollow"  class="url" >walu</a> writes: 先mark，慢慢看</li><li><a href="http://www.laruence.com/2011/11/09/2277.html" >2011/11/09</a>, <a href="http://www.pztai.com"  rel="external nofollow"  class="url" >taylor</a> writes: 最近在看php的源代码，觉得好多东西都得再看几遍才能理解</li><li><a href="http://www.laruence.com/2011/11/09/2277.html" >2011/11/09</a>, <a href="http://developerblog.org"  rel="external nofollow"  class="url" >浪</a> writes: 这个必须得顶啊</li><li><a href="http://www.laruence.com/2011/11/09/2277.html" >2011/11/10</a>, <a href="http://mcknight0219.blogspot.com/"  rel="external nofollow"  class="url" >Qiang</a> writes: 大神，你的那个示意图画得不怎么直观啊:)</li><li><a href="http://www.laruence.com/2011/11/09/2277.html" >2011/11/10</a>, liexusong writes: 不太好懂~</li><li><a href="http://www.laruence.com/2011/11/09/2277.html" >2011/12/03</a>, henosteven writes: 估计的看几遍 , 才会懂</li><li><a href="http://www.laruence.com/2011/11/09/2277.html" >2011/12/31</a>, <a href="http://waibo.net/"  rel="external nofollow"  class="url" >Rhythm</a> writes: 膜拜！这个东东，看来得多读几遍才能理解。</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/03/04/1894.html"  title="深入理解PHP内存管理之谁动了我的内存" >深入理解PHP内存管理之谁动了我的内存</a></li><li><a href="http://www.laruence.com/2011/01/27/1854.html"  title="深入理解PHP内存管理之一个低概率Core的分析" >深入理解PHP内存管理之一个低概率Core的分析</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/11/09/2277.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>JsonSerializable接口</title>
		<link>http://www.laruence.com/2011/10/10/2204.html</link>
		<comments>http://www.laruence.com/2011/10/10/2204.html#comments</comments>
		<pubDate>Mon, 10 Oct 2011 03:16:23 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[转载]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[JsonSerializable]]></category>
		<category><![CDATA[jsonSerialize]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php5.4]]></category>
		<category><![CDATA[PHP5.4新特性]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2204</guid>
		<description><![CDATA[    昨天funlake提醒了我, 应该把一些PHP的新动向传播一下. 
<blockquote>
恭喜候鸟加入了pdt,有什么新进展别忘了给咱cn phper通报一下呀。
</blockquote>

  今天我来为大家介绍一下5.4中对Json做的一个改进.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2011/10/10/2204.html"  title="Permanet Link to JsonSerializable接口" >http://www.laruence.com/2011/10/10/2204.html</a></li>
<li>转载文章</li>
</ul></div>
<p>
    昨天funlake提醒了我, 应该把一些PHP的新动向传播一下. </p>
<blockquote><p>
恭喜候鸟加入了pdt,有什么新进展别忘了给咱cn phper通报一下呀。
</p></blockquote>
<p>  那么, 今天为大家介绍一下5.4中对Json做的一个改进.</p>
<p>  Json是Ajax应用中最为通用的数据传输格式(协议),  主流的编程语言都带有对Json的支持,  在PHP中, 有json_encode/json_decode, 可以很方便的构造Json数据格式.</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
echo json_encode(array(1,2,3,4));
?&gt;

//[1,2,3,4]
</pre>
<p> 也可以Json化一个对象:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
$o = new stdclass;
$o-&gt;a = 42;
echo json_encode($o);
?&gt;

//{&quot;a&quot;:42}
</pre>
<p>  但这样就有个问题,  现实生活中的对象是很复杂的, Json的这种默认只对属性做操作的做法有的时候是不能解决问题的, 比如我们希望通过私有成员来做一些计算得到最后的Json化数据, 又或者我们希望用一个字符串来代替一个object.</p>
<p>  在以前, 那你只能自己拼凑Json串了.  不过感谢Sara, 在5.4中,  Json新增了一个JsonSerializable接口,  任何实现了这个接口的类, 需要定义一个jsonSerialize()方法, 这个方法会在对这个类的对象做Json化的时候被调用, 这个时候你就可以在这个方法内 , 随意调整最终的Json化的结果:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
class JsonTest implements JsonSerializable {
    private $a, $b;

    public function __construct($a, $b) {
        $this-&gt;a = $a;
        $this-&gt;b = $b;
    }

    public function jsonSerialize() {
        return $this-&gt;a + $this-&gt;b;
    }
}

echo json_encode(new JsonTest(23, 42));
?&gt;

//65
</pre>
<p> 下面是个稍微复杂点的例子:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
$data = array(
    new stdClass();
    new JsonTest(1,2),
    new JsonTest(3,4),
    array(5,6)
);
echo json_encode($data);
?&gt;

//[{},3,7,[5,6]]
</pre>
<p>   最后提醒一下, PHP 5.4还处于开发阶段,  在最终release之前, 这些特性都可能被调整或者更改.  如果大家有任何建议, 也欢迎反馈, 帮助我们使得PHP变得更好.</p>
<p>   谢谢</p>
<p>   PS: 这个特性最初由Johannes在他自己的blog中介绍: <a href="http://schlueters.de/blog/archives/135-Jason,-let-me-help-you!.html" >http://schlueters.de/blog/archives/135-Jason,-let-me-help-you!.html</a><br/>
   <script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/10/10/2204.html" >2011/10/10</a>, wclssdn writes: 感觉也不是很有用. 既然encode的时候写了对象. 那干嘛不直接调用对象的一个方法呢?比如就叫_jsonSerialize...</li><li><a href="http://www.laruence.com/2011/10/10/2204.html" >2011/10/10</a>, wynn writes: 定义标准化interface的意义远超过单纯的实现某个功能。

比如说原本某处有段代码是：
$o = new myClass();
/* do something */
echo json_encode($o);
后来因为某种原因，myClass的某个属性被移除，改为计算得出，那么只要改一改myClass的定义，实现JsonSerializable接口，并实现jsonSerialize方法即可，其他地方都不需要变动。

如果用自定义某个方法的方式来实现同样的功能（比如就叫_jsonSerialize），那么在初期就要给所有需要被json化的对象定义此方法（具体内容很可能就是简单的 return $this;），平白增加了复杂度，降低了效率。

所有开发人员都遵循一样的标准，也会让程序的沟通维护更加简单。</li><li><a href="http://www.laruence.com/2011/10/10/2204.html" >2012/01/21</a>, <a href="http://fwso.cn/php/php5-4%e6%96%b0%e7%89%b9%e6%80%a7%e5%b0%8f%e7%bb%93/"  rel="external nofollow"  class="url" >PHP5.4新特性小结 | 实践.最佳 - 行.思.悟</a> writes: [...] 参考：http://www.laruence.com/2011/10/10/2204.html [...]</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/10/10/2239.html"  rel="bookmark"  title="Permanent Link: 让Json更懂中文(JSON_UNESCAPED_UNICODE)" >让Json更懂中文(JSON_UNESCAPED_UNICODE)</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/07/14/2115.html"  title="Zend引擎的优化" >Zend引擎的优化</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/09/23/2171.html"  title="我对PHP5.4的一个改进" >我对PHP5.4的一个改进</a></li><li><a href="http://www.laruence.com/2010/02/02/1272.html"  title="注意PHP5.2.11之后的json_decode" >注意PHP5.2.11之后的json_decode</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/10/10/2204.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>mysqlnd插件mysqlnd_ms的介绍</title>
		<link>http://www.laruence.com/2011/10/05/2192.html</link>
		<comments>http://www.laruence.com/2011/10/05/2192.html#comments</comments>
		<pubDate>Wed, 05 Oct 2011 12:06:37 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[MySQL/PostgreSQL]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[fail over]]></category>
		<category><![CDATA[load balancing]]></category>
		<category><![CDATA[mysqlnd]]></category>
		<category><![CDATA[mysqlnd_ms]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[read-write splitting]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2192</guid>
		<description><![CDATA[ 从PHP5.3开始, MySQL team专为PHP开发的MySQL连接库mysqlnd(MySQL native driver for PHP)终于和PHP一起发布了. mysqlnd的主要目的是为了解决长久以来mysql和php的license的问题.  它将作为PHP的源代码的一部分和PHP一起发布.

    今天, 我要为大家介绍一个mysqlnd的插件:mysqlnd_ms,  这个插件是由mysqlnd的开发者Andrey Hristov,<a href="http://blog.ulf-wendel.de/">Ulf Wendel</a>和<a href="http://schlueters.de/blog/">johannes</a>一起开发的, 目前发布在PECL: <a href="http://pecl.php.net/package/mysqlnd_ms">mysqlnd_ms</a>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/10/05/2192.html"  title="Permanet Link to mysqlnd插件mysqlnd_ms的介绍" >http://www.laruence.com/2011/10/05/2192.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    从PHP5.3开始, MySQL team专为PHP开发的MySQL连接库mysqlnd(MySQL native driver for PHP)终于和PHP一起发布了. mysqlnd的主要目的是为了解决长久以来mysql和php的license的问题.  它将作为PHP的源代码的一部分和PHP一起发布.</p>
<p>    今天, 我要为大家介绍一个mysqlnd的插件:mysqlnd_ms,  这个插件是由mysqlnd的开发者Andrey Hristov,<a href="http://blog.ulf-wendel.de/" >Ulf Wendel</a>和<a href="http://schlueters.de/blog/" >johannes</a>一起开发的, 目前发布在PECL: <a href="http://pecl.php.net/package/mysqlnd_ms" >mysqlnd_ms</a></p>
<p>    在这个扩展的介绍页面我们可以看到它的功能描述:</p>
<blockquote><p>
The replication and load balancing plugin is a plugin for the mysqlnd library. It can be used with PHP MySQL extensions (ext/mysql, ext/mysqli, PDO_MySQL). if they are compiled to use mysqlnd. The plugin inspects queries to do read-write splitting. Read-only queries are send to configured MySQL replication slave servers all other queries are redirected to the MySQL replication master server. Very little, if any, application changes required, dependent on the usage scenario required.
</p></blockquote>
<p>    这个扩展, 主要实现了, 连接保持和切换, 负载均衡和读写分离等, 也就是说, 这个扩展会去分别PHP发给MySQL的query,  如果是&#8221;读&#8221;的query, 就会把query发送给从库(配置中指明), 并且支持负载均衡;  而如果是&#8221;写&#8221;的query,  就会把query发送给主库.</p>
<p>    不过这个扩展需要搭配mysqlnd一起使用(从PHP5.4 beta1开始, 我们已经把mysqlnd作为mysql, mysqli, pdo的默认链接目标, 当然, 你也可以通过&#8211;with-mysql=***来制定你想要链接到libmysql).</p>
<p>    这个扩展使用的方法也很简单, 首先在<b>php.ini</b>中定义配置:</p>
<pre name="code"  class="sh_ini"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
mysqlnd_ms.enable=1
mysqlnd_ms.ini_file=/path/to/mysqlnd_ms_plugin.ini
</pre>
<p>    之后, 在你指明的mysqlnd_ms_plugin.ini中配置好MySQL的主从库就好了:</p>
<pre name="code"  class="sh_ini"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
[myapp]
master[]=localhost:/tmp/mysql.sock
slave[]=192.168.2.27:3306
</pre>
<p>   <b>博文发出以后, Ulf提醒我, 从1.1.0开始, 配置文件改为JSON格式:</b></p>
<blockquote><p>
Ulf_Wendel: @laruence >Thx for the blog. Please note, mysqlnd_ms config format was changed in 1.1.0. Now JSON based
</p></blockquote>
<p>   所以新的配置应该类似于如下格式:</p>
<pre name="code"  class="sh_json"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
{
    &quot;myapp&quot;: {
        &quot;master&quot;: {
            &quot;master_0&quot;: {
                &quot;host&quot;: &quot;localhost&quot;,
                &quot;socket&quot;: &quot;\/tmp\/mysql.sock&quot;
            }
        },
        &quot;slave&quot;: {
            &quot;slave_0&quot;: {
                &quot;host&quot;: &quot;192.168.2.27&quot;,
                &quot;port&quot;: &quot;3306&quot;
            }
        }
    }
}
</pre>
<p>   链接方式修改如下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
/* Load balanced following &quot;myapp&quot; section rules from the plugins config file */
$mysqli = new mysqli(&quot;myapp&quot;, &quot;username&quot;, &quot;password&quot;, &quot;database&quot;);
$pdo = new PDO('mysql:host=myapp;dbname=database', 'username', 'password');
$mysql = mysql_connect(&quot;myapp&quot;, &quot;username&quot;, &quot;password&quot;);
?&gt;
</pre>
<p>   然后就和你之前一样的来开发了. </p>
<p>   如果希望获得更多信息, 可以参看: <a href="http://php.net/mysqlnd_ms" >http://php.net/mysqlnd_ms</a><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_ini.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_ini.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_json.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/10/06</a>, 风起 writes: 不错, 读写分离这点很需要</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/10/07</a>, <a href="http://baloyou.gotoip55.com/archives/433"  rel="external nofollow"  class="url" >mysqlnd插件mysqlnd_ms的介绍 | 风雪之隅 - 候鸟的博客</a> writes: [...] 通过mysqlnd插件mysqlnd_ms的介绍 | 风雪之隅.      wordpress 源码解读 (1) [...]</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/10/09</a>, <a href="http://xiaobin.net"  rel="external nofollow"  class="url" >Robin</a> writes: 请问鸟哥有在生产环境使用么？

一直在关注mysqlnd_ms，不过发现从统计数据来看（iva http://url.cn/0DdMJr）下载的人并不多，不太敢贸然使用。

另外也关注mysql proxy，但是问题好像也不少(via http://url.cn/1r9DR5)</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/10/10</a>, <a href="http://www.6pima.cn"  rel="external nofollow"  class="url" >中山网站建设</a> writes: 不错哟，学习一下</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/11/19</a>, 深空 writes: 不知道能否很好识别事务</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/11/25</a>, <a href="http://www.cnxct.com/some-errors-on-compile-php-5-3-8-with-pdo_mysql-and-mysqlnd/"  rel="external nofollow"  class="url" >php5.3.8中编译pdo_mysql的艰难历程 | CNXCT小组的博客</a> writes: [...] 这里是将pdo_mysql作为一个拓展引入使用的。在php5.3中，PHP开发组把mysqlnd作为默认的连接MYSQL的数据库驱动来使用，据官方描述，节省内存40%，速度更快，当然或许是为了解决许可协议的问题。详情见：mysqlnd插件mysqlnd_ms的介绍。 两种方法都可以，运维同事都尝试了，由于时间关系，他们没做过多的尝试研究，就转向更紧急的项目了。 [...]</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2008/09/20/523.html"  rel="bookmark"  title="Permanent Link: PHP5.3 α2初体验" >PHP5.3 α2初体验</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/10/05/2192.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>PHP正则之递归匹配</title>
		<link>http://www.laruence.com/2011/09/30/2179.html</link>
		<comments>http://www.laruence.com/2011/09/30/2179.html#comments</comments>
		<pubDate>Fri, 30 Sep 2011 05:20:33 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Recursive pattern]]></category>
		<category><![CDATA[regular]]></category>
		<category><![CDATA[正则]]></category>
		<category><![CDATA[递归匹配]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2179</guid>
		<description><![CDATA[我记得早前有同事问, 正则是否能处理括号配对的正则匹配. 

     比如, 对于如下的待匹配的字符串:
<coolcode lang="bash" linenum="off">
   ((())) 
</coolcode>
    就是一个括号配对的字符串. 而对于如下的待匹配字符串:
<coolcode lang="bash" linenum="off">
   ((()
</coolcode>
   则不是一个括号配对的字符串.

   在以前, 这种情况, 正则无法处理,  最多只能处理固定层数的递归,  而无法处理无线递归的情况...  而在perl 5.6以后, 引入了一个新的特性: <a href="http://www.php.net/manual/en/regexp.reference.recursive.php">Recursive patterns</a>, 使得这种需求可以被正确的处理.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/09/30/2179.html"  title="Permanet Link to PHP正则之递归匹配" >http://www.laruence.com/2011/09/30/2179.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
     我记得早前有同事问, 正则是否能处理括号配对的正则匹配. </p>
<p>     比如, 对于如下的待匹配的字符串:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
   ((()))
</pre>
<p>    就是一个括号配对的字符串. 而对于如下的待匹配字符串:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
   ((()
</pre>
<p>   则不是一个括号配对的字符串.</p>
<p>   在以前, 这种情况, 正则无法处理,  最多只能处理固定层数的递归,  而无法处理无线递归的情况&#8230;  而在perl 5.6以后, 引入了一个新的特性: <a href="http://www.php.net/manual/en/regexp.reference.recursive.php" >Recursive patterns</a>, 使得这种需求可以被正确的处理.</p>
<p>    Recursive pattern引入了一个新的符号(?R),  这个符号可以表示: 正则模式本身, 比如:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
    #1(?R)*#
</pre>
<p>     我们来仔细看一下, 这个正则, 首先它匹配数字&#8221;1&#8243;,  然后(?R)*表示,  正则式本身, 也就是说,  可以认为是:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
    #1(正则本身(正则本身).....)*#
</pre>
<p>     于是, 对于文章开头说到的情况:&#8221;括号配对&#8221;,   可以写下如下的正则式:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
     #\((?R)*\)#
</pre>
<p>     就可以正确处理.</p>
<p>     这里提醒一下, 用的时候, 要注意一定要给递归一个截至条件, 比如如果上面的例子写成:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
   #1(?R)#
</pre>
<p>     那么, 就不会正常工作, 因为这个展开以后表示要匹配无限多个&#8221;1&#8243;,  所以在上面的例子中, 写作了(?R)*, 让它可以有一个截止的条件(可以为0个).</p>
<p>     另外, 这个新特性也支持序号引用(?index), 比如:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
     #(1)(2)(3)(?3)(?2)(?1)#
</pre>
<p>     表示匹配, 123321.</p>
<p>     如果想更多的了解这个新特性, 可以参看: <a href="http://www.php.net/manual/en/regexp.reference.recursive.php" >http://www.php.net/manual/en/regexp.reference.recursive.php</a></p>
<p>     感谢windy, 和<a href="http://weibo.com/byyloo" >shiwei</a>提供的帮助 <img src="http://www.laruence.com/wp-includes/images/smilies/icon_smile.gif"  alt=":)"  class="wp-smiley" /> <script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/09/30/2179.html" >2011/09/30</a>, <a href="http://www.cnxct.com"  rel="external nofollow"  class="url" >CFC4N</a> writes: PHP的正则递归(又称迭代)这个特性，在5.2版本已经支持了吧。不清楚5.2的版本用的是PCRE那个版本。最早是php的版本支持的不清楚。是不是PHP5就开始支持了？
我觉得这种递归匹配字符串的事情，最好不要用正则去实现，尽量程序+算法实现，正则去做的话，回溯太多了，很容易引起 回溯太多，引爆了堆栈，类似http://www.laruence.com/2010/06/08/1579.html 这里的问题。</li><li><a href="http://www.laruence.com/2011/09/30/2179.html" >2011/09/30</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @CFC4N 恩, 有可能, 不过我是最近才发现的, 惭愧, :)</li><li><a href="http://www.laruence.com/2011/09/30/2179.html" >2011/09/30</a>, sunshinehao writes: 有错字。无限递归打成了无线递归</li><li><a href="http://www.laruence.com/2011/09/30/2179.html" >2011/10/04</a>, <a href="http://read.osser.me/?p=294"  rel="external nofollow"  class="url" >PHP正则之递归匹配 | love googlereader</a> writes: [...] &#26412;&#25991;&#22320;&#22336;: http://www.laruence.com/2011/09/30/2179.html [...]</li><li><a href="http://www.laruence.com/2011/09/30/2179.html" >2011/10/08</a>, Jay writes: 《正则表达式30分钟入门教程》中也有一个例子，讲的也是括号匹配。</li><li><a href="http://www.laruence.com/2011/09/30/2179.html" >2011/10/10</a>, <a href="http://blog.thinkinlamp.com/?p=776"  rel="external nofollow"  class="url" >Thinking In LAMP Blog &raquo; Blog Archive &raquo; PHP每月通讯（2011年10月）</a> writes: [...] http://www.laruence.com/2011/09/30/2179.html 　　PHP正则之递归匹配 [...]</li><li><a href="http://www.laruence.com/2011/09/30/2179.html" >2011/10/13</a>, luckgo writes: 这个问题我一直纠集，我知道?R可递归匹配，但我的问题是，如果“递归”匹配a(b(c(d(e))))，注意，前面的a是必须的，我试过了很多办法，没法达到目的。
请问下，我说的这个问题能解决吗？（不是硬性匹配，是递归，要有通用性）</li><li><a href="http://www.laruence.com/2011/09/30/2179.html" >2011/11/23</a>, Zone writes: 什么时候能支持平衡组呢？</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/09/30/2179.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>我对PHP5.4的一个改进</title>
		<link>http://www.laruence.com/2011/09/23/2171.html</link>
		<comments>http://www.laruence.com/2011/09/23/2171.html#comments</comments>
		<pubDate>Fri, 23 Sep 2011 15:22:25 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[improve]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP5.4新特性]]></category>
		<category><![CDATA[zend]]></category>
		<category><![CDATA[改进]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2171</guid>
		<description><![CDATA[   插播个消息, 今天, 我终于获得了Zend的编辑权限,  Zend是PHP源代码中最为核心的部分, 也是最为敏感的地方, 对于这部分的权限控制的一直很严格.  但也是我加入PHP开发组以后, 一直想得到的权限. :)

   好了, 言归正传, 今天对PHP5.4的Zend引擎做了一个改进,  改进了参数不兼容的报警信息. 具体的来说:]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/09/23/2171.html"  title="Permanet Link to 我对PHP5.4的一个改进" >http://www.laruence.com/2011/09/23/2171.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   插播个消息, 今天, 我终于获得了Zend的编辑权限,  Zend是PHP源代码中最为核心的部分, 也是最为敏感的地方, 对于这部分的权限控制的一直很严格.  但也是我加入PHP开发组以后, 一直想得到的权限. <img src="http://www.laruence.com/wp-includes/images/smilies/icon_smile.gif"  alt=":)"  class="wp-smiley" /> </p>
<p>   好了, 言归正传, 今天对PHP5.4的Zend引擎做了一个改进,  改进了参数不兼容的报警信息. 具体的来说:</p>
<p>   对于如下的例子:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
class Sub implements ArrayAccess {
    public function offsetSet() {
    }
}
?&gt;
</pre>
<p>   在目前大家一定会得到类似如下的错误信息:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
PHP Fatal error:  Declaration of Sub::offsetSet() must be compatible
with that of ArrayAccess::offsetSet()
</pre>
<p>   这里有个问题, 错误信息并没有告诉我们, 正确的参数应该是什么样子,  我们除了去查手册(或者看源代码), 没办法得知.</p>
<p>   于是, 在开发组经过提议, 讨论之后, 我今天做了一个改进, 改进之后, 将会得到如下的错误信息:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
Fatal error: Declaration of Sub::offsetSet() must be compatible with
ArrayAccess::offsetSet($offset, $value)
</pre>
<p>  当然, 这个对用户自定的类也是有效的, 如下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
class Foo {
}

Abstract Class Base {
    abstract public function test(Foo $foo, array $bar,
              $option = NULL, $extra = 16777215) ;
}

class Sub extends Base {
    public function test(Foo $foo, array $bar) {
    }
}
?&gt;
</pre>
<p> 将会得到如下的错误信息:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
PHP Fatal error:  Declaration of Sub::test() must be compatible with
Base::test(Foo $foo, array $bar, $option = NULL, $extra = 16777215)
</pre>
<p>  reversion: <a href="http://svn.php.net/viewvc?view=revision&#038;revision=317206" >http://svn.php.net/viewvc?view=revision&#038;revision=317206</a><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/23</a>, lanisle writes: 群管比群主给力多了，摸泄天天没正经的~</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/23</a>, <a href="http://www.zui88.com"  rel="external nofollow"  class="url" >林绍强</a> writes: 支持，中国phper的骄傲</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/24</a>, kernel writes: 加上这功能吧 https://bugs.php.net/bug.php?id=34392</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/24</a>, xLight writes: 如果我没理解错，看来5.4已经支持指定传入参数变量的类型了啊。
good news</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/24</a>, <a href="http://snowheart.sinaapp.com"  rel="external nofollow"  class="url" >戴韬_雪心</a> writes: 5.3就已经支持指定传入参数变量的类型了……很隐蔽的方式，嗯</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/24</a>, <a href="http://lilazhou.wordpress.com/2011/09/23/222/"  rel="external nofollow"  class="url" >傻子日志</a> writes: [...] &#25105;&#23545;PHP5.4&#30340;&#19968;&#20010;&#25913;&#36827; [...]</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/24</a>, <a href="http://blog.56swun.com"  rel="external nofollow"  class="url" >小牛哥</a> writes: 非常好，很厉害啊。</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/26</a>, 怪物宝 writes: 厉害啊，佩服</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/27</a>, 神仙 writes: 这个很实在</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/27</a>, <a href="http://www.zwsos.com"  rel="external nofollow"  class="url" >asy</a> writes: 我的偶象，支持国产PHPER</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/09/30</a>, wclssdn writes: @xLight 很久以前就支持了吧- -. 5.0以后? 
嗯. 不错~~ 有了这个提示还是蛮人性化的.... 能省好多键盘鼠标... (脾气不好的程序员总砸键盘.... 或者摔鼠标....</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/04</a>, <a href="http://read.osser.me/?p=294"  rel="external nofollow"  class="url" >PHP正则之递归匹配 | love googlereader</a> writes: [...] &#25105;&#23545;PHP5.4&#30340;&#19968;&#20010;&#25913;&#36827; [...]</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/06</a>, <a href="http://blog.csdn.net/rainkid"  rel="external nofollow"  class="url" >rainkid</a> writes: 恭喜恭喜，我的环境下面一直报这个错误，但不知道是什么问题，laruence能帮忙看一下么
PHP Fatal error:  Cannot override final method Exception::getPrevious() in Unknown on line 0</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/06</a>, <a href="http://blog.csdn.net/rainkid"  rel="external nofollow"  class="url" >rainkid</a> writes: 这个问题好像找到了，是之前安装你的yaf框架，我去掉这个扩展就没有这个错误了，我这已经更新到最新版本了，楼主帮忙看看</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/06</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @rainkid 你的PHP版本是?</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/06</a>, <a href="http://blog.csdn.net/rainkid"  rel="external nofollow"  class="url" >rainkid</a> writes: 我的PHP version 是 5.3.5</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/06</a>, <a href="http://blog.csdn.net/rainkid"  rel="external nofollow"  class="url" >rainkid</a> writes: 补充一下，我的系统是ubuntu 64bit</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/06</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @rainkid 没道理啊, 代码中对于5.3以上都会注释掉getPrevious的逻辑, 你是不是编译的时候, 用错了phpize和php-config?</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/07</a>, <a href="http://blog.csdn.net/rainkid"  rel="external nofollow"  class="url" >rainkid</a> writes: 这个应该不会，我下了5.3.6的源码在看，但没有编译过，本地安装的了5.3.5的，我找了一下phpize和php-config都只有一个，应该不存在您说的问题。</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/07</a>, <a href="http://blog.csdn.net/rainkid"  rel="external nofollow"  class="url" >rainkid</a> writes: php-config -v
显示的版本是:5.3.5-1ubuntu7.2</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/07</a>, <a href="http://blog.csdn.net/rainkid"  rel="external nofollow"  class="url" >rainkid</a> writes: 我去http://pecl.php.net/package/yaf下载了最新的版本
重新编译OK了，非常感谢！</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/07</a>, <a href="http://www.joysk.com"  rel="external nofollow"  class="url" >joysk</a> writes: 表示对大牛的膜拜一下！
哈哈</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/09</a>, funlake writes: 这算是小试牛刀。
好戏应还在后头。
鼓掌！</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2011/10/20</a>, Kyli writes: 基本上PHP里你是我的偶像了</li><li><a href="http://www.laruence.com/2011/09/23/2171.html" >2012/01/01</a>, PHPer writes: 崇拜一下你呗，向你学习</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/03/29/1949.html"  rel="bookmark"  title="Permanent Link: 深入理解PHP原理之Session Gc的一个小概率Notice" >深入理解PHP原理之Session Gc的一个小概率Notice</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  rel="bookmark"  title="Permanent Link: PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2008/09/20/523.html"  rel="bookmark"  title="Permanent Link: PHP5.3 α2初体验" >PHP5.3 α2初体验</a></li><li><a href="http://www.laruence.com/2011/07/02/2097.html"  rel="bookmark"  title="Permanent Link: PHP5.4的新特性" >PHP5.4的新特性</a></li><li><a href="http://www.laruence.com/2011/10/10/2232.html"  rel="bookmark"  title="Permanent Link: 二进制直接量(binary number format)" >二进制直接量(binary number format)</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/10/10/2204.html"  title="JsonSerializable接口" >JsonSerializable接口</a></li><li><a href="http://www.laruence.com/2011/07/14/2115.html"  title="Zend引擎的优化" >Zend引擎的优化</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/09/23/2171.html/feed</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>回答下在bugs.php上的一个问题</title>
		<link>http://www.laruence.com/2011/09/22/2152.html</link>
		<comments>http://www.laruence.com/2011/09/22/2152.html#comments</comments>
		<pubDate>Thu, 22 Sep 2011 06:55:44 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[bugs.php]]></category>
		<category><![CDATA[getter]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[__get]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2152</guid>
		<description><![CDATA[<p>
   今天在bugs.php.net上, 有一个用QQ邮箱的用户发了一个问题(<a href="http://bugs.php.net/55731">#55731</a>).

   他问, 为什么, 如下的代码, 会调用俩遍getter:

   一开始, 我只是简单的回答了下, 和他在__get中再次获取$this->elmname有关系.  后来这个同学又要追问原因,  我只好用我那糟糕的英语给他解释.
   
   可能用英语没太讲明白, 我现在用中文解释下吧.
</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/09/22/2152.html"  title="Permanet Link to 回答下在bugs.php上的一个问题" >http://www.laruence.com/2011/09/22/2152.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   今天在bugs.php.net上, 有一个用QQ邮箱的用户发了一个问题(<a href="http://bugs.php.net/55731" >#55731</a>).</p>
<p>   他问, 为什么, 如下的代码, 会调用俩遍getter:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
class Example{
    private $p1;
    private $p2;
    function __construct($a){
        $this-&gt;p1=$a;
    }
    function __get($elmname){
        echo &quot;Call_get()&quot;;
        return $this-&gt;$elmname;
    }
    function __isset($name){
        return isset($this-&gt;$name);
    }
    function __unset($name){
        unset($this-&gt;$name);
    }
}
$example = new Example(&quot;v1&quot;);
unset($example-&gt;p1);
echo $example-&gt;p1;
//输出
//Call_get()Call_get()
</pre>
<p>   一开始, 我只是简单的回答了下, 和他在__get中再次获取$this->elmname有关系.  后来这个同学又要追问原因,  我只好用我那糟糕的英语给他解释.</p>
<p>   可能用英语没太讲明白, 我现在用中文解释下吧.</p>
<p>   (补充: 文章发出以后, 有不少同学认为我把简单问题搞复杂了, 他们认为unset($example->p1)也会触发一次getter.   所以我先解答下这一点: <b>&#8220;非&#8221;读&#8221;上下文不会触发对__get的调用&#8221;</b>. 这一点也很容易验证, 大家可以试试.  要不然我也不会专门写这个文章来讨论这个问题.)</p>
<p>   首先. 这个问题的关键原因是,  unset掉一个private的变量.</p>
<p>   在我们获取一个对象的变量(&#8220;读&#8221;上下文)的时候, 其实是首先被翻译成ZEND_FETCH_OBJ_R中间指令(opcode),  那么到了真正执行期的时候, 这条opcode会导致最终调用到zend_read_property, 我把关键代码罗列如下: </p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
.....
    /* make zend_get_property_info silent if we have getter - we may want to use it */
    property_info = zend_get_property_info_quick(zobj-&gt;ce, member, (zobj-&gt;ce-&gt;__get != NULL), key TSRMLS_CC);

    if (UNEXPECTED(!property_info) ||
        ((EXPECTED((property_info-&gt;flags &amp; ZEND_ACC_STATIC) == 0) &amp;&amp;
         property_info-&gt;offset &gt;= 0) ?
            (zobj-&gt;properties ?
                ((retval = (zval**)zobj-&gt;properties_table[property_info-&gt;offset]) == NULL) :
                (*(retval = &amp;zobj-&gt;properties_table[property_info-&gt;offset]) == NULL)) :
            (UNEXPECTED(!zobj-&gt;properties) ||
              UNEXPECTED(zend_hash_quick_find(zobj-&gt;properties, property_info-&gt;name,
                property_info-&gt;name_length+1, property_info-&gt;h, (void **) &amp;retval) == FAILURE)))) {
        zend_guard *guard = NULL;

        if (zobj-&gt;ce-&gt;__get &amp;&amp;
            zend_get_property_guard(zobj, property_info, member, &amp;guard) == SUCCESS &amp;&amp;
            !guard-&gt;in_get) {
            /* have getter - try with it! */
            Z_ADDREF_P(object);
            if (PZVAL_IS_REF(object)) {
                SEPARATE_ZVAL(&amp;object);
            }
            guard-&gt;in_get = 1; /* prevent circular getting */
            rv = zend_std_call_getter(object, member TSRMLS_CC);
            guard-&gt;in_get = 0;
</pre>
<p>   上面的代码解释如下:</p>
<p>    1.  首先调用zend_get_property_info_quick, 尝试在对象对应的类(zend_class_entry * zobj->ce)中寻找该属性的声明信息(public, protect, name, hash), zend_get_property_info_quick会在找不到, 或者找到了, 但是不容许访问(外部访问私有,保护变量)的时候, 返回NULL</p>
<p>    2.  如果找到对应的属性信息, 则将依照属性信息中的属性名作为接下来查找的属性名(在PHP中, 私有属性的命名为&#8221;\0class_name\0property_name\0&#8243;, 保护属性的命名为:&#8221;\0*\0property_name\0&#8243;, 公有属性的命名为&#8221;property_name\0&#8243;)</p>
<p>    2.  如果没有找到相关的声明信息(未定义属性),  则尝试直接从对象的属性集中寻找(zobj_properties, 这是因为PHP是一个很灵活的语言, 你可以动态的给一个对象则加属性), 如果找到, 成功返回.</p>
<p>    3.  如果在对象的属性集合中也没有找到, 则判断对象是否申明了__get魔术方法, 如果没有则报告找不到返回失败.</p>
<p>    4.  如果有__get魔术方法, 为了避免发生嵌套递归, 首先查询是否已经存在该属性名的guard, 如果有判断guard->in_get是否为真, 如果为真表示发生递归了,则失败返回.  如果没有, 则设置一个名为属性名的guard(<b>请注意这里</b>), 然后调用__get</p>
<p>    5.  调用__get如果找到则成功返回, 否则失败结束.</p>
<p>    现在, 让我们来看看文章开头的例子.</p>
<p>    1. 调用zend_read_property,  zobj是$example, member是p1</p>
<p>    2. 调用zend_get_property_info_quick查询p1属性信息, 因为此时的作用域是全局作用域, PHP不容许直接访问对象的私有属性, 所以zend_get_property_info_quick返回NULL</p>
<p>    3. 尝试从zobj->properties中寻找p1, 因为p1被unset掉了, 所以不存在, 没找到</p>
<p>    4. 发现$example有__get魔术方法.</p>
<p>    5. 查找是否有为&#8221;p1&#8243;设置的guard, 没有.</p>
<p>    6. 设置一个名为&#8221;p1&#8243;的guard, 然后调用$example->__get (<b>输出Call_get()</b>)</p>
<p>    7. 在$example->__get中,  我们尝试获取$this->p1, 于是再来一次::</p>
<p>    8. 调用zend_read_property,  zobj是$example, member是p1</p>
<p>    9.调用zend_get_property_info_quick查询p1属性信息, 因为此时的作用域是example, 所以zend_get_property_info_quick返回成功</p>
<p>    10. <b>将返回的属性信息中的属性名&#8221;\0example\0p1\0&#8243;作为要查询的属性名</b></p>
<p>    11. 尝试从zobj->properties中寻找p1, 因为p1被unset掉了, 所以不存在, 没找到</p>
<p>    12. 发现$example有__get魔术方法.</p>
<p>    13. 查找是否有为&#8221;\0example\0p1\0&#8243;设置的guard, 没有.</p>
<p>    14. 设置一个名为&#8221;\0example\0p1\0&#8243;的guard, 然后调用$example->__get (<b>输出Call_get()</b>)</p>
<p>    15. 在$example->__get中,  我们尝试获取$this->p1, 于是再来一次::</p>
<p>    然后重复8,9,10,11,12. </p>
<p>    16,  <b>查找是否有为&#8221;\0example\0p1\0&#8243;设置的guard, 发现有递归产生, 报告错误, 失败返回.</b><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/22</a>, <a href="http://www.showframework.com/"  rel="external nofollow"  class="url" >showframework</a> writes: 没这么复杂吧..
unset($xample-&gt;p1);echo $example-&gt;p1;
这本身就是两次__get啊
unset语句里面那个语句一次__get
echo 后面一次__get</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/22</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @showframework 呵呵,你可以试试unset($example->p1), 看看有没有调用...</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/22</a>, wynn writes: 楼上这个说法不对，unset的执行过程中不调用__get的，这一点很容易验证，直接沿用正文这段代码，把__get里面的return那行注释掉就可以用来测试了。</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/22</a>, <a href="http://aiyooyoo.com"  rel="external nofollow"  class="url" >萝卜青菜</a> writes: 没细看，对象的定义中有一个变量是用来防止__set,__get方法递归调用的</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/22</a>, <a href="http://blog.csdn.net/rainkid"  rel="external nofollow"  class="url" >rainkid</a> writes: 楼主扩展研究太多了，简单的事情搞复杂了。

使用一次$example-&gt;p1就调用一次__get方法

unset($example-&gt;p1);
echo $example-&gt;p1;

这里明显使用的两次，当然会输出两次“Call_get”;</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/22</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @rainkid   sigh, 发表意见前, 一定动手验证下.</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/23</a>, <a href="http://www.fzbog.net"  rel="external nofollow"  class="url" >風之紫色</a> writes: 楼主说的没错，把unset($this-&gt;$name);这行注释掉，就很容易看出来了</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/24</a>, <a href="http://lilazhou.wordpress.com/2011/09/23/222/"  rel="external nofollow"  class="url" >傻子日志</a> writes: [...] &#26412;&#25991;&#22320;&#22336;: http://www.laruence.com/2011/09/22/2152.html [...]</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/24</a>, helloyou writes: 还是有点疑问:
既然已经unset了,为何第9步中还是返回了"examplep1"? 

比较下面这两个类:
class Ex1{
  private $var;

  function __construct(){
        unset($this-&gt;var);
  }

  function __get($elmname){
        echo "call __get\n";
        return $this-&gt;$elmname;
  }

}

class Ex2{

        function __construct(){
        }

        function __get($elmname){
                echo "call __get\n";
                return $this-&gt;$elmname;
        }

}

$ex1=new Ex1();
$ex2=new Ex2();

var_dump($ex1);
var_dump($ex2);

echo $ex2-&gt;var;
echo $ex1-&gt;var;

在var_dump处,两个类给出完全相同的输出,
但是下面的echo却给出不同的结果(一个两次,一个一次call __get),还是让人觉得奇怪.</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/24</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @helloyou 因为p1的属性信息是存在类中的, 你unset只是对一个对象实例</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/09/24</a>, helloyou writes: 嗯,这样彻底清楚了,谢谢</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/10/10</a>, <a href="http://blog.thinkinlamp.com/?p=776"  rel="external nofollow"  class="url" >Thinking In LAMP Blog &raquo; Blog Archive &raquo; PHP每月通讯（2011年10月）</a> writes: [...] http://www.laruence.com/2011/09/22/2152.html 　　回答下在bugs.php上的一个问题 [...]</li><li><a href="http://www.laruence.com/2011/09/22/2152.html" >2011/10/27</a>, newer writes: 其实，这个和访问类中不存在的变量会自动创建变量是一个原理吧</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/09/22/2152.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>PHP的版本发布历程</title>
		<link>http://www.laruence.com/2011/09/19/2148.html</link>
		<comments>http://www.laruence.com/2011/09/19/2148.html#comments</comments>
		<pubDate>Mon, 19 Sep 2011 12:26:37 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[历史]]></category>
		<category><![CDATA[发布]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2148</guid>
		<description><![CDATA[<p>
   整理了一下, PHP的进化历程,  原文在这里: <a href="https://wiki.php.net/internals/module_api_no">https://wiki.php.net/internals/module_api_no</a>
</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/09/19/2148.html"  title="Permanet Link to PHP的版本发布历程" >http://www.laruence.com/2011/09/19/2148.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   整理了一下, PHP的进化历程,  原文在这里: <a href="https://wiki.php.net/internals/module_api_no" >https://wiki.php.net/internals/module_api_no</a>
</p>
<table class="inline" >
<tbody>
<tr class="row0" >
<td class="col0" ><strong>Date</strong></td>
<td class="col1" ><strong>Version</strong></td>
</tr>
<tr class="row1" >
<td class="col0 leftalign" > June 8 1995  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> Tools 1.0 </td>
</tr>
<tr class="row2" >
<td class="col0 leftalign" > Oct 17 1995  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym>/FI 1.92 </td>
</tr>
<tr class="row3" >
<td class="col0" > Mar 16 1996 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym>/FI 1.99k </td>
</tr>
<tr class="row4" >
<td class="col0" > June 16 1997 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym>/FI 2.0b12 </td>
</tr>
<tr class="row5" >
<td class="col0" > Oct 29 1997 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 3.0a1 </td>
</tr>
<tr class="row6" >
<td class="col0" > Nov 12 1997 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym>/FI 2.0 </td>
</tr>
<tr class="row7" >
<td class="col0 leftalign" > Dec 8 1997  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 3.0b1 </td>
</tr>
<tr class="row8" >
<td class="col0 leftalign" > Jan 9 1998  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym>/FI 2.0.1 </td>
</tr>
<tr class="row9" >
<td class="col0 leftalign" > June 6 1998  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 3.0 </td>
</tr>
<tr class="row10" >
<td class="col0 leftalign" > July 4 1998  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 3.0.1 </td>
</tr>
<tr class="row11" >
<td class="col0 leftalign" > Mar 1 1999  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 3.0.7 </td>
</tr>
<tr class="row12" >
<td class="col0" > July 19 1999 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.0b1 </td>
</tr>
<tr class="row13" >
<td class="col0 leftalign" > Jan 1 2000  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 3.0.13 </td>
</tr>
<tr class="row14" >
<td class="col0" > Oct 21 2000 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 3.0.18 </td>
</tr>
<tr class="row15" >
<td class="col0 leftalign" > May 22 2000  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.0 </td>
</tr>
<tr class="row16" >
<td class="col0" > Oct 11 2000 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.0.3 </td>
</tr>
<tr class="row17" >
<td class="col0" > Apr 30 2001 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.0.5 </td>
</tr>
<tr class="row18" >
<td class="col0" > June 23 2001 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.0.6 </td>
</tr>
<tr class="row19" >
<td class="col0" > Dec 10 2001 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.1.0 </td>
</tr>
<tr class="row20" >
<td class="col0" > Dec 26 2001 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.1.1 </td>
</tr>
<tr class="row21" >
<td class="col0" > Feb 27 2002 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.1.2 </td>
</tr>
<tr class="row22" >
<td class="col0" > Apr 22 2002 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.2.0 </td>
</tr>
<tr class="row23" >
<td class="col0 leftalign" > May 13 2002  </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.2.1 </td>
</tr>
<tr class="row24" >
<td class="col0" > July 22 2002 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.2.2 </td>
</tr>
<tr class="row25" >
<td class="col0" > Sep  6 2002 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.2.3 </td>
</tr>
<tr class="row26" >
<td class="col0" > Dec 27 2002 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.0 </td>
</tr>
<tr class="row27" >
<td class="col0" > Feb 17 2003 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.1 </td>
</tr>
<tr class="row28" >
<td class="col0" > May 29 2003 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.2 </td>
</tr>
<tr class="row29" >
<td class="col0" > Aug 25 2003 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.3 </td>
</tr>
<tr class="row30" >
<td class="col0" > Nov 03 2003 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.4 </td>
</tr>
<tr class="row31" >
<td class="col0" > Jul 13 2004 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.0.0 &amp; <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.8 </td>
</tr>
<tr class="row32" >
<td class="col0" > Aug 12 2004 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.0.1 </td>
</tr>
<tr class="row33" >
<td class="col0" > Sep 03 2004 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.0.2 </td>
</tr>
<tr class="row34" >
<td class="col0" > Sep 22 2004 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.9 </td>
</tr>
<tr class="row35" >
<td class="col0" > Dec 15 2004 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.0.3 &amp; <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.10 </td>
</tr>
<tr class="row36" >
<td class="col0" > Mar 31 2005 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.0.4 &amp; <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.3.11 </td>
</tr>
<tr class="row37" >
<td class="col0" > Jul 11 2005 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.0 </td>
</tr>
<tr class="row38" >
<td class="col0" > Sep 06 2005 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.0.5 </td>
</tr>
<tr class="row39" >
<td class="col0" > Oct 31 2005 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.1 </td>
</tr>
<tr class="row40" >
<td class="col0" > Nov 24 2005 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.1.0 </td>
</tr>
<tr class="row41" >
<td class="col0" > Nov 28 2005 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.1.1 </td>
</tr>
<tr class="row42" >
<td class="col0" > Jan 12 2006 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.1.2 </td>
</tr>
<tr class="row43" >
<td class="col0" > Jan 13 2006 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.2 </td>
</tr>
<tr class="row44" >
<td class="col0" > May 01 2006 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.1.3 </td>
</tr>
<tr class="row45" >
<td class="col0" > May 04 2006 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.1.4 </td>
</tr>
<tr class="row46" >
<td class="col0" > Aug 03 2006 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.3 </td>
</tr>
<tr class="row47" >
<td class="col0" > Aug 17 2006 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.1.5 &amp; <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.4 </td>
</tr>
<tr class="row48" >
<td class="col0" > Aug 24 2006 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.1.6 </td>
</tr>
<tr class="row49" >
<td class="col0" > Nov 02 2006 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.0 </td>
</tr>
<tr class="row50" >
<td class="col0" > Feb 08 2007 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.1 &amp; <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.5 </td>
</tr>
<tr class="row51" >
<td class="col0" > Mar 01 2007 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.6 </td>
</tr>
<tr class="row52" >
<td class="col0" > May 03 2007 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.2 &amp; <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.7 </td>
</tr>
<tr class="row53" >
<td class="col0" > Jun 01 2007 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.3 </td>
</tr>
<tr class="row54" >
<td class="col0" > Aug 30 2007 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.4 </td>
</tr>
<tr class="row55" >
<td class="col0" > Nov 09 2007 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.5 </td>
</tr>
<tr class="row56" >
<td class="col0" > Jan 03 2008 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.8 </td>
</tr>
<tr class="row57" >
<td class="col0" > May 01 2008 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.6 </td>
</tr>
<tr class="row58" >
<td class="col0" > Aug 07 2008 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 4.4.9 </td>
</tr>
<tr class="row59" >
<td class="col0" > Dec 04 2008 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.7 </td>
</tr>
<tr class="row60" >
<td class="col0" > Dec 08 2008 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.8 </td>
</tr>
<tr class="row61" >
<td class="col0" > Feb 26 2009 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.9 </td>
</tr>
<tr class="row62" >
<td class="col0" > Jun 18 2009 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.10 </td>
</tr>
<tr class="row63" >
<td class="col0" > Jun 30 2009 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.0 </td>
</tr>
<tr class="row64" >
<td class="col0" > Sep 17 2009 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.11 </td>
</tr>
<tr class="row65" >
<td class="col0" > Nov 19 2009 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.1 </td>
</tr>
<tr class="row66" >
<td class="col0" > Dec 17 2009 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.12 </td>
</tr>
<tr class="row67" >
<td class="col0" > Feb 25 2010 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.13 </td>
</tr>
<tr class="row68" >
<td class="col0" > Mar 04 2010 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.2 </td>
</tr>
<tr class="row69" >
<td class="col0" > Jul 22 2010 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.3 &amp; <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.14 </td>
</tr>
<tr class="row70" >
<td class="col0" > Dec 09 2010 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.15 </td>
</tr>
<tr class="row71" >
<td class="col0" > Dec 10 2010 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.4 </td>
</tr>
<tr class="row72" >
<td class="col0" > Dec 16 2010 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.16 </td>
</tr>
<tr class="row73" >
<td class="col0" > Jan 06 2011 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.5 &amp; <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.2.17 </td>
</tr>
<tr class="row74" >
<td class="col0" > Mar 17 2011 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.6 </td>
</tr>
<tr class="row75" >
<td class="col0" > Aug 18 2011 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.7 </td>
</tr>
<tr class="row76" >
<td class="col0" > Aug 23 2011 </td>
<td class="col1" > <acronym title="Hypertext Preprocessor" >PHP</acronym> 5.3.8 </td>
</tr>
</tbody>
</table>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/09/19/2148.html" >2011/09/20</a>, <a href="http://zhys9.com"  rel="external nofollow"  class="url" >zhys9</a> writes: 记得刚开始搞PHP时是4.3的时代， 还能经常看到.php3的代码 :D，现在已然是时过境迁咯</li><li><a href="http://www.laruence.com/2011/09/19/2148.html" >2011/09/20</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @zhys9 呵呵, 都快10年了... :)</li><li><a href="http://www.laruence.com/2011/09/19/2148.html" >2011/09/21</a>, wclssdn writes: 刚开始学的时候, 就是PHP5的表示很庆幸~~ 
现在好多人貌似都在用5.2.6吧.... 不知道升级PHP版本会对现有程序造成哪些影响?</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  title="GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/09/19/2148.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>关于做PHP扩展开发的一些资源</title>
		<link>http://www.laruence.com/2011/09/13/2139.html</link>
		<comments>http://www.laruence.com/2011/09/13/2139.html#comments</comments>
		<pubDate>Tue, 13 Sep 2011 08:14:01 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP extension]]></category>
		<category><![CDATA[开发php扩展]]></category>
		<category><![CDATA[扩展开发]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2139</guid>
		<description><![CDATA[  最近有个感觉, 越来越多的人开始从事PHP扩展开发的工作(越来越多的人来问问题了, 呵呵)

   在这里先说声抱歉, 有的时候, 有的同学的邮件进了垃圾邮件没有办法及时回复.

   为了方便大家, 我在这里罗列一些可能用到的资源.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/09/13/2139.html"  title="Permanet Link to 关于做PHP扩展开发的一些资源" >http://www.laruence.com/2011/09/13/2139.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   最近有个感觉, 越来越多的人开始从事PHP扩展开发的工作(越来越多的人来问问题了, 呵呵)</p>
<p>   在这里先说声抱歉, 有的时候, 有的同学的邮件进了垃圾邮件没有办法及时回复.</p>
<p>   为了方便大家, 我在这里罗列一些可能用到的资源.</p>
<p>   1. 首先, 要推荐一本书 《Extending and Embedding PHP》,  如果你有时间, 我建议你在做之前好好读读这本书(目前没有中文版)</p>
<p>   2. Google/Baidu 这个就不用多说了吧</p>
<p>   3. PHP的源代码中,包含了一些编写良好的&#8221;例子&#8221;, 都在ext/目录下, 绝大部分Zend_API的使用, 都在里面有例子.</p>
<p>   4. pecl-dev at lists.php.net 这个邮件组是扩展开发的交流邮件组, 如果你实在是Google/baidu不到你的问题的答案, 可以发邮件到这个邮件组提问, 不过, 一般来说, 要有耐心等待回复(大部分人和我们有15个小时的时差, 当然, 如果我看到了, 我会尽量回复)</p>
<p>   5. efnet #php.pecl 这里聚集了pecl开发者,  你也可以来这里提问(我整天都在上面), 不过这里只能说英文,  另外提问的时候要注意不要直接粘贴代码, 而应该使用pastebin之类的工具(所以还是建议大家发邮件到pecl-dev)</p>
<p>   6. 尽量编写一些phpt测试用例(phpt的写法在每个标准扩展下面都有例子, tests目录下), 来测试你的扩展.</p>
<p>   7. 测试的时候用&#8211;enable-debug编译PHP, 来测试你的扩展, 你要做到执行你的扩展逻辑, 不输出任何错误信息</p>
<p>   8. 使用valgrind检测内存泄露.</p>
<p>  希望对大家有帮助. </p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/13</a>, <a href="http://www.startfeel.com"  rel="external nofollow"  class="url" >Ray</a> writes: 鸟哥。。。书名呢？</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/13</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: 好了, 呵呵, 换成书名号了...</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/13</a>, Qianfeng writes: 鸟哥，我想知道你的，开发桌面是什么系统？。。

还有日常使用的桌面是否同一个~~</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/13</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @Qianfeng 我自己用windows, 虚拟机是Linux, 在Linux下开发</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/13</a>, <a href="http://blog.iterse.com"  rel="external nofollow"  class="url" >iterse's blog</a> writes: 鸟哥，V5！</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/14</a>, <a href="http://walu.sinaapp.com"  rel="external nofollow"  class="url" >walu</a> writes: 《Extending and Embedding PHP》我正在翻译，项目地址：http://phpbook.sinaapp.com 如果鸟哥偶尔有空，还请帮忙斧正。:-)</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/14</a>, 早起的菜鸟 writes: 鸟哥 你是不是那个写私房菜的鸟哥啊？都是大神啊！我也取了鸟的名字，希望能够沾沾你们的才气</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/14</a>, <a href="http://010blog.sinaapp.com"  rel="external nofollow"  class="url" >Me.strone</a> writes: 没注意，原来是传说中的鸟哥啊……看了你写的那两个私房菜，很不错。希望多多出好书！我们就多多向你学习了。</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/14</a>, <a href="http://www.laruence.com/"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @walu 我看了下,翻译的挺好, 不过有一点, 就是那本书成书已经好几年了, 最近PHP改变较多, 尤其是5.4, 底层结构变化也比较多, 如果忠实翻译还好, 否则可能要考虑新加入的东西:)</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/09/14</a>, <a href="http://www.laruence.com/"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @早起的菜鸟 @Me.strone 诶, 私房菜的鸟哥是台湾的, 搞Linux的, :&lt;</li><li><a href="http://www.laruence.com/2011/09/13/2139.html" >2011/10/10</a>, <a href="http://blog.thinkinlamp.com/?p=776"  rel="external nofollow"  class="url" >Thinking In LAMP Blog &raquo; Blog Archive &raquo; PHP每月通讯（2011年10月）</a> writes: [...] http://www.laruence.com/2011/09/13/2139.html 　　关于做PHP扩展开发的一些资源 [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/04/28/719.html"  title="用C/C++扩展你的PHP" >用C/C++扩展你的PHP</a></li><li><a href="http://www.laruence.com/2009/08/18/1042.html"  title="保证PHP扩展的依赖关系" >保证PHP扩展的依赖关系</a></li><li><a href="http://www.laruence.com/2008/04/16/19.html"  title="编写提供对象给PHP使用的Module" >编写提供对象给PHP使用的Module</a></li><li><a href="http://www.laruence.com/2011/07/02/2102.html"  title="Zend Parameters Parser新增类型描述符介绍" >Zend Parameters Parser新增类型描述符介绍</a></li><li><a href="http://www.laruence.com/2011/06/19/2047.html"  title="PLua &#8211; Lua for PHP" >PLua &#8211; Lua for PHP</a></li><li><a href="http://www.laruence.com/2010/09/04/1736.html"  title="Yaf-一个PHP扩展实现的PHP框架" >Yaf-一个PHP扩展实现的PHP框架</a></li><li><a href="http://www.laruence.com/2008/08/16/301.html"  title="扩展PHP[Extending PHP](一)" >扩展PHP[Extending PHP](一)</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/09/13/2139.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Plua进入Pecl</title>
		<link>http://www.laruence.com/2011/08/04/2131.html</link>
		<comments>http://www.laruence.com/2011/08/04/2131.html#comments</comments>
		<pubDate>Thu, 04 Aug 2011 05:28:49 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP Extension]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[lua]]></category>
		<category><![CDATA[pecl]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2131</guid>
		<description><![CDATA[  一个月以前, 我开发了一个php扩展(<a href="http://www.laruence.com/2011/06/19/2047.html"> PLua – Lua for PHP </a>), 支持在PHP中调用Lua脚本
  
    后续, 发现在pecl中有一个类似的扩展, lua

    在和lua的作者johannes, Andreas讨论过以后,  我们一致认为, 应该只保留一个lua扩展.

    考虑到Plua的设计更加符合PHP思维习惯, 功能上也比lua要更加丰富, 大家就一致决定把plua作为新的lua标准扩展, 当然plua也会借鉴lua现在的一些优点.

    目前plua已经整合到pecl lua的svn中,  等和johannes确认以后, 就会发布release: <a href="http://pecl.php.net/package/lua">Lua</a>
]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/08/04/2131.html"  title="Permanet Link to Plua进入Pecl" >http://www.laruence.com/2011/08/04/2131.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    一个月以前, 我开发了一个php扩展(<a href="http://www.laruence.com/2011/06/19/2047.html" > PLua – Lua for PHP </a>), 支持在PHP中调用Lua脚本</p>
<p>    后续, 发现在pecl中有一个类似的扩展, lua</p>
<p>    在和lua的作者johannes, Andreas讨论过以后,  我们一致认为, 应该只保留一个lua扩展.</p>
<p>    考虑到Plua的设计更加符合PHP思维习惯, 功能上也比lua要更加丰富, 大家就一致决定把plua作为新的lua标准扩展, 当然plua也会借鉴lua现在的一些优点.</p>
<p>    目前plua已经整合到pecl lua的svn中,  等和johannes确认以后, 就会发布release: <a href="http://pecl.php.net/package/lua" >Lua</a></p>
<p>    后续Plua的project将不再维护, 相关文档也将在lua中重新编写&#8230;</p>
<p>    Btw: 这也是我的第二个PECL扩展..</p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/08/04/2131.html" >2011/08/04</a>, walu writes: 呵呵，鸟哥出品，必属精品～

小弟正在努力学习PHP内核的这个东东，鸟哥你就是偶像+榜样啊</li><li><a href="http://www.laruence.com/2011/08/04/2131.html" >2011/08/09</a>, rwl writes: 支持下，不简单。</li><li><a href="http://www.laruence.com/2011/08/04/2131.html" >2011/08/12</a>, <a href="http://blog.iterse.com"  rel="external nofollow"  class="url" >Iterse's blog</a> writes: 学习，学习！</li><li><a href="http://www.laruence.com/2011/08/04/2131.html" >2011/09/21</a>, rman writes: Would you be so kind - compile php win32 extension dll, and upload it to googlecode, please..</li><li><a href="http://www.laruence.com/2011/08/04/2131.html" >2011/09/27</a>, <a href="http://www.zwsos.com"  rel="external nofollow"  class="url" >sdk</a> writes: 鸟哥，，是台湾那个鸟哥么，LINUX学习的那个么</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/06/19/2047.html"  rel="bookmark"  title="Permanent Link: PLua &#8211; Lua for PHP" >PLua &#8211; Lua for PHP</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/06/19/2047.html"  title="PLua &#8211; Lua for PHP" >PLua &#8211; Lua for PHP</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/08/04/2131.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Zend引擎的优化</title>
		<link>http://www.laruence.com/2011/07/14/2115.html</link>
		<comments>http://www.laruence.com/2011/07/14/2115.html#comments</comments>
		<pubDate>Thu, 14 Jul 2011 03:13:38 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php5.4]]></category>
		<category><![CDATA[PHP5.4新特性]]></category>
		<category><![CDATA[zend vm]]></category>
		<category><![CDATA[zend引擎]]></category>
		<category><![CDATA[优化]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2115</guid>
		<description><![CDATA[ 在PHP 5.4的更新list上, 有一句: 提升了Zend引擎的性能, 减少了内存占用.

    那么, 到底是怎么提升的呢?
]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/07/14/2115.html"  title="Permanet Link to Zend引擎的优化" >http://www.laruence.com/2011/07/14/2115.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    在PHP 5.4的更新list上, 有一句: 提升了Zend引擎的性能, 减少了内存占用.</p>
<p>    那么, 到底是怎么提升的呢?</p>
<h3>避免不必要的Hashtable</h3>
<p>   我们知道在PHP中, 类的属性/静态属性/常量, 都是保存在Hashtable中的,  而在以前, 即使一个类没有申明属性/静态属性/常量, Zend引擎也会为他们分配Hashtable.</p>
<p>    而在现在,  这个过程被优化了,  只有在有元素的时候才会分配Hashtable.</p>
<p>    这样就避免一些emalloc/efree操作, 减少一些内存占用.</p>
<h3>四元式优化</h3>
<p>    在PHP中, 真正执行的是Opcodes,  一个Opcodes包含3个固定的操作数,  result, left, right,  在以前, 这三个操作数每一个都包含一个zval, 即使根本用不到的时候, 比如没有右操作数的时候,  还会为右操作数分配一个zval.</p>
<p>    而在现在,  所有的操作数将不再直接包含zval,  而是包含一个literal table的指针,  每一个op array都会包含一个literal table.<br/>
    并且znode也做了相应的调整.  </p>
<p>    这样一来, 也能减少一些内存占用. 从之前的(32位操作系统)一个opcode占用72byte, 到现在的28byte.</p>
<p>    另外, 对于string,  literal table还会保存一份这个string的预先计算的hash值, 避免了在运行时多次计算. 从而提高一部分性能.</p>
<h3>字面字符串</h3>
<p>    就好像C语言中, 代码中的字面字符串, 会保存在一个固定段内(数据段), 在整个执行时期, 这些字符串都是常量字符串,不能被修改,不能被free.</p>
<p>    PHP也借鉴了这样的思想, 提出一个Internal string的概念, 在PHP代码中的字面量字符串, 将会一次分配, 并前在整个执行期都不能被修改. </p>
<p>    PHP在copy_zval, free zval等操作的时候, 会对internal string特别处理, 避免不必要的free和复制.</p>
<p>    并且这些字面量字符串的hash值将会被预先计算,  这样一来,  对于字符串比较 ==, 以及hashtable中的hash计算来说, 都可以直接使用这个预先计算的hash值, 从而能提高一部分性能.</p>
<h3>其他</h3>
<p>     当然,  还有很多优化点, 比如优化了opcode, 减少了一些不必要的opcodes,  在此就不一一赘述了. </p>
<h3>对比</h3>
<p>下面是PHP开发小组内部测试的一些数据:</p>
<p>原生PHP, 没有Opcode Cache:</p>
<table>
<tbody>
<tr>
<th>                       </th>
<th> php-trunk </th>
<th> patched </th>
<th> inprovement </th>
</tr>
<tr>
<td> bench.php (sec)       </td>
<td>      4.31 </td>
<td>    3.49 </td>
<td>         19% </td>
</tr>
<tr>
<td> micro_bench.php (sec) </td>
<td>     19.78 </td>
<td>   14.63 </td>
<td>         26% </td>
</tr>
</tbody>
</table>
<p>一些实际的应用:</p>
<table>
<tbody>
<tr>
<th>                     </th>
<th> php-trunk </th>
<th> pathced </th>
<th> improvement </th>
</tr>
<tr>
<td> blog (req/sec)      </td>
<td>      59.3 </td>
<td>    66.2 </td>
<td>         12% </td>
</tr>
<tr>
<td> drupal (req/sec)    </td>
<td>    1073.9 </td>
<td>  1084.8 </td>
<td>          1% </td>
</tr>
<tr>
<td> fw (req/sec)        </td>
<td>     105.3 </td>
<td>   111.8 </td>
<td>          6% </td>
</tr>
<tr>
<td> hello (req/sec)     </td>
<td>    5362.5 </td>
<td>  5351.4 </td>
<td>          0% </td>
</tr>
<tr>
<td> qdig (req/sec)      </td>
<td>     243.4 </td>
<td>   253.7 </td>
<td>          4% </td>
</tr>
<tr>
<td> typo3 (req/sec)     </td>
<td>     355.3 </td>
<td>   382.6 </td>
<td>          8% </td>
</tr>
<tr>
<td> wordpress (req/sec) </td>
<td>     101.8 </td>
<td>   108.5 </td>
<td>          7% </td>
</tr>
<tr>
<td> xoops (req/sec)     </td>
<td>      70.3 </td>
<td>    78.5 </td>
<td>         12% </td>
</tr>
<tr>
<td> scrum (req/sec)     </td>
<td>      86.5 </td>
<td>   104.2 </td>
<td>         20% </td>
</tr>
</tbody>
</table>
<p>     从这些数据来看, 性能提升还是很明显的..</p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/07/14</a>, <a href="http://www.xoopsengine.org"  rel="external nofollow"  class="url" >D.J.</a> writes: 谢谢Laruence的深度解析。
Benchmark这部分有公开的文章描述么？</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/07/14</a>, cute writes: 好消息啊！
在PHP代码中的字面量字符串, 将会一次分配, 并前再整个执行器都不能被修改.
潜在？</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/07/14</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @D.J. 没有公开的数据, 因为只是作为RFC的辅助说明数据.</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/07/14</a>, Locke writes: 并前再整个执行器都不能被修改.
=======================
并且在整个执行期都不能被修改。</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/07/14</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @Locke  thanks, 呵呵, 我是有名的别字大王....</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/09/07</a>, <a href="http://warpigallen.sinaapp.com/?p=50"  rel="external nofollow"  class="url" >warpig&#039;s blog &raquo; [转]PLua – Lua for PHP</a> writes: [...] 本文地址: http://www.laruence.com/2011/07/14/2115.html [...]</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/09/24</a>, <a href="http://lilazhou.wordpress.com/2011/09/23/222/"  rel="external nofollow"  class="url" >傻子日志</a> writes: [...] Zend&#24341;&#25806;&#30340;&#20248;&#21270; [...]</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/10/04</a>, <a href="http://read.osser.me/?p=294"  rel="external nofollow"  class="url" >PHP正则之递归匹配 | love googlereader</a> writes: [...] Zend&#24341;&#25806;&#30340;&#20248;&#21270; [...]</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/10/09</a>, funlake writes: 为啥没有joomla1.7的测试结果.</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/10/25</a>, Xorcerer writes: 谢谢你的分析。
另外，第二张，既最后一张表格的 “pathced” 也许应为 “patched”</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/11/01</a>, gan writes: 兄弟乃PHP大牛，我会经常关注你的网站，希望多多发表，多多透露，我们也会多多提关于PHP的建议。</li><li><a href="http://www.laruence.com/2011/07/14/2115.html" >2011/11/03</a>, <a href="http://qwerwqre"  rel="external nofollow"  class="url" >ewrqwer</a> writes: qwerqwerqwerqrew</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2008/08/15/274.html"  rel="bookmark"  title="Permanent Link: PHP 源代码分析 V0.0.2" >PHP 源代码分析 V0.0.2</a></li><li><a href="http://www.laruence.com/2008/07/16/225.html"  rel="bookmark"  title="Permanent Link: Zend Engine幻想" >Zend Engine幻想</a></li><li><a href="http://www.laruence.com/2010/06/21/1608.html"  rel="bookmark"  title="Permanent Link: PHP调试技术手册发布(1.0.0 pdf)" >PHP调试技术手册发布(1.0.0 pdf)</a></li><li><a href="http://www.laruence.com/2011/11/18/2305.html"  rel="bookmark"  title="Permanent Link: GBK编码PHP脚本导致语法错误(Zend Multibyte)" >GBK编码PHP脚本导致语法错误(Zend Multibyte)</a></li><li><a href="http://www.laruence.com/2011/10/10/2229.html"  rel="bookmark"  title="Permanent Link: 函数类型提示(Callable typehint)" >函数类型提示(Callable typehint)</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/10/10/2204.html"  title="JsonSerializable接口" >JsonSerializable接口</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li><li><a href="http://www.laruence.com/2011/09/23/2171.html"  title="我对PHP5.4的一个改进" >我对PHP5.4的一个改进</a></li><li><a href="http://www.laruence.com/2011/07/13/2110.html"  title="PHP RFC: 让PHP的foreach支持list" >PHP RFC: 让PHP的foreach支持list</a></li><li><a href="http://www.laruence.com/2011/02/13/1870.html"  title="加速PHP的ECHO" >加速PHP的ECHO</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/07/14/2115.html/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

