php bug的这个bug怎么破

PHP 语言有BUG_百度知道我的PHP代码,写一个简易的计算器,BUG很多,应该怎么改?_百度知道这是不是PHP的bug? - 开源中国社区
当前访客身份:游客 [
当前位置:
&$array = [ 1, 2, 3 ];
&echo implode(',', $array), &\n&;
&foreach ($array as &$value) { }
&echo implode(',', $array), &\n&;
&foreach ($array as $value) { }
&echo implode(',', $array), &\n&;
1,2,3 1,2,3 1,2,2
共有9个答案
<span class="a_vote_num" id="a_vote_num_
不是 &bug 第一个 foreach 用的是引用
也就是 在第一个foreach 执行 之后, $value 这个变量就是$array 这个数组最后一个元素的引用
当你执行第二个foreach的时候,数组的元素赋值给value的时候上就是在改变 $array这个数组的最后一个元素的值
所以实际上foreach执行时 数组的值是这么变化的
[1,2,1] & &[1,2,2] 注意当变成[1,2,2] 的时候,由于数组最后一个元素的值已经改变,所以赋值给$value 的时候, 依然为 2
所以第二个foreach执行完之后 数组实际上就已经变成了 [1,2,2] 了
<span class="a_vote_num" id="a_vote_num_
没有BUG,你的foreach循环体根本没有语句执行。
<span class="a_vote_num" id="a_vote_num_
&&&&可以说是bug,也可以说不是。不过PHP开发组表示这不是一个bug,也不会修改这个语言特性。但是这确实是一个bug,很多人都认为就是bug。
&&&&这个特性确实很容易让人困惑,这种很诡异的不符合直觉的代码可以归为bug。虽然可以用opcode来解释,不过这个属于从结果来找原因了。
--- 共有 2 条评论 ---
: 我看到的评论,主要是说PHP缺少块级作用域,会受到function-level的副作用影响。我觉得还是有道理的
(2年前)&nbsp&
其实是符合代码逻辑的。也说不上是bug。
最后一个&$value在循环之后还存在。
下面的$value就是这个对数组最后一个元素的引用。所以这样。
引用循环后,需要unset掉引用变量。至少每次循环都用不同的变量吧。
我敢打赌,c或c++的应该不会犯这个错误。因为他们使用变量都是很小心的。纯php像我这样的,就比较容易掉进去。
(2年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
你的数组定义写的不对,下面是php手册的片段:
The weird behaviour of references in foreach remains as long as in PHP 5.2.08& (Linux) and PHP 5.2.9 (Windows XP).&& The simplest example would be:
&?php &&& $a = array('a', 'b','c'); &&& foreach($a as &$row){ && & && //you don't have to do anything here && & & } &&& print_r($a); &&& foreach($a as $row){ && & & echo &&br /&&.$row; &&& } ?&
the result of print_r will be correct - array of ('a','b','c') values. The second foreach, however, would
produce a,b,b. For all arrays, regardless of size, it would be the n-1 element &(the element right before the last one). Eg. for 'a','b','c','d','e','f', the script would produce a,b,c,d,e,e.
There are few solutions to this:
1. safest - avoid using r& so instead of
&?php foreach($a as &$row){ &&& // do something, eg. &&& $row = trim($row); } ?&
you would use
&?php foreach($a as $i=&$row){ &&& // do something on row, eg. &&& $row = trim($row); &&& // replace the row in the table &&& $a[$i]=$row; } ?& decrease of performance is the cost, however
2. equally safe and more usable - unset the element reference right after the foreach loop with references, eg.: &?php &&& $a = array('a', 'b','c'); &&& foreach($a as &$row){ && & && //you don't have to do anything here && & & } && & & unset ($row)); // it is safe now to use $row again &&& print_r($a); &&& foreach($a as $row){ && & & echo &&br /&&.$row; &&& } ?&
3. use ref it seems that iterations work correct if you use &$row in both loops or don't use it in any:
&?php &&& $a = array('a', 'b','c'); &&& foreach($a as &$row){ && & && //you don't have to do anything here && & & } && & & print_r($a); && & & // works OK now even without unset($row) &&& foreach($a as &$row){ && & & echo &&br /&&.$row; &&& } ?&
4. use references in foreach only inside
outside the function scope it should be safe
&?php function cleanTable($a){ &&& foreach($a as &$row){ && & && $row = trim($row); &&& } }
$a = array('a','b','c'); cleanTable($a); foreach($a as $row){ echo &&br /&&.$row; } ?&
drawbacks: NONE! I Quite contrary, the code looks more tidy.
5. avoid using the same variable names for referenced and non- for example, in the first case use &$rRow, and in the second one - $row. It's neither elegant, nor efficient, though, as each new variable lowers the application performance a bit. &?php &&& $a = array('a', 'b','c'); &&& foreach($a as &$rRow){ // $rRow for 'referenced row' && & && //you don't have to do anything here && & & } &&& print_r($a);
&&& foreach($a as $row){ && & & echo &&br /&&.$row; &&& } ?&
--- 共有 3 条评论 ---
: 你们都好时髦,我还在5.3。。。
(2年前)&nbsp&
$arrr = [];
//这个是php5.4开始添加进来的,数组的精简语法
(2年前)&nbsp&
这个是 5.4版本以上的 array 所以是[]
(2年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
这不算bug吧
第一个foreach以后 &$value 一直指向 数组最后一个位置&
第二个foreach里 实际上是没循环一次 都把当前值赋给最后一个位置
第二个forecah里打印数组的变化就可以比较清楚了
$array = [ 1, 2, 3 ];
foreach ($array as &$value) { }
echo implode(',', $array), &\n&;
echo '---------------foreach------------------'.PHP_EOL;
foreach ($array as $value) {
&&&&echo implode(',', $array), &\n&;
echo '---------------endforeach---------------'.PHP_EOL;
echo implode(',', $array), &\n&;
<span class="a_vote_num" id="a_vote_num_
第一个foreach结束时$value变量并未销毁,并且$value此时是$array[2]的一个引用。
当第二个foreach开始时
$array[2] = $value = $array[0] = 1
此时array=[1,2,1]
接着 $array[2] = $value = $array[1] = 2
此时 array = [1,2,2]
$array[2] = $value = $array[2] = 2
结果就成这样了
<span class="a_vote_num" id="a_vote_num_
首先楼主要明白PHP一个很重要的事:全局变量和局部变量。
所谓全局变量,则一般为$_GET $_POST $_REQUEST 这些PHP自身提供的全局变量,方便给各位开发时在任何地方都可以轻松调用。(试想,在a.php中检查$_GET中的某个值是否合适,然后请求b.php里的方法,在该方法里再次检测$_GET这个值是否合适——这个过程需要传递参数吗?不用)
也可以使用global关键字声明全局变量。例如任何地方 global $global_val = &我是全局变量,你在任何地方都可以echo到我!我的存在是为了方便你在这次生命周期中拥有我&;
局部变量是指在函数块内部的变量,例如function me(){$var1 = &我是局部变量,在这个函数之外你echo不出我&;}
<span class="a_vote_num" id="a_vote_num_
foreach里多了一个&
<span class="a_vote_num" id="a_vote_num_
这些东西还是你自己理解了原理在说这些话!
更多开发者职位上
有什么技术问题吗?
脚踩两只鞋的其它问题
类似的话题PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 &#8211; 左手代码 右手诗
PHP为了避免数字索引和数字字符串索引(注1)的混乱, 引入了zend_symtable_*系列函数, 并应用于数组中.
这样一来, 数字字符串索引也就会被当作数字索引, 然而总是有一些情况, 是PHP的维护者没有想到的&#8230;
比如, 类型转换时刻:
鉴于很多朋友好心的提示, 使用json_deocde的第二个参数就可以直接得到数组.
我说明下, 如下的代码是我有意而为之, 并不是为了json_decode, 而是为了构造一个&有问题&的数组.
在PHP5.2.*下(json version 1.2.1):
$data = array(
123 =& 'laruence',
$value = json_encode($data);
= json_decode($value);
= (array)$
var_dump($arr);
另提供了如下的更简单的构造方法:
$obj=new stdC
$obj-&{'123'} = &laruence&;
$arr = (array)$
var_dump($arr);
此时, 问题就出现了, 上面得到的输出是:
array(1) {
string(8) &laruence&
现在,你郁闷吧, 因为数组键是字符串, 而通过正常渠道访问的时候, PHP都会自动把数字字符串转换成数字, 所以:
print_r($arr[123]);
//PHP Notice:
Undefined offset:
123 in ***
print_r($arr[&123&]);
//PHP Notice:
Undefined offset:
123 in ***
var_dump(array_key_exists(&123&, $arr));
//bool(false)
我已经报了Bug, 不过PHP本身也不保证类型转换的一致性, 所以PHP维护者最后认为是不是Bug都无所谓了, 大家平时注意即可:
本文中所说的字符串数字和之前的文章中所说的numeric string有一点不同, 在zend_symtable_*系列函数中, 只会吧/^-?[^0][0-9]*$/这样的字符串认为是数字字符串. 相关核心逻辑如下:
#define HANDLE_NUMERIC(key, length, func) {
register char *tmp=
if (*tmp=='-') {
if ((*tmp&='0' && *tmp&='9')) do {
char *end=key+length-1;
if (*tmp++=='0' && length&2) {
while (tmp&end) {
if (!(*tmp&='0' && *tmp&='9')) {
if (tmp==end && *tmp=='0') {
if (*key=='-') {
idx = strtol(key, NULL, 10);
if (idx!=LONG_MIN) {
idx = strtol(key, NULL, 10);
if (idx!=LONG_MAX) {
} while (0);
PS:我这里只有5.2.8, 5.2.11俩个版本, 各位读者如果有其他版本的PHP, 帮忙测试下是否在你的版本下也存在这个问题. 谢谢
另: 谢谢提供这个问题, 原问题是和Memcached相关的.
Related Posts:
Tags: , , , ,
Filed in ,
Leave a Reply
开发组核心成员, 顾问, PHP7主要开发者, , , 等开源项目作者.

我要回帖

更多关于 php bug 排查 的文章

 

随机推荐