问题讨论:程序 C/C++ Java GUI编程 ASP Php Shell Perl Web开发 软件工程 三大件 机箱 存储设备 光存储 音频设备 视频设备 外设 购机
asp php java C CGI .net vb delphi unix&linux sql Word Excel WPS OutLook Powerpoint Dreamweaver FPage/Golive CSS/HTML DOM/JS
热门词:流程图 excel 入侵检测 vss Windows 安全漏洞 QQ空间 事件编程 MFC

 程序设计交流 > Php 

发现php的一个BUG.其实都好几年了.有人说是trick(陷阱)

[2008-11-20 2:56:17] [来源: 百家电脑学院] [我要投稿]

2008-10-8 11:42achun.shx发现php的一个BUG.其实都好几年了.有人说是trick(陷阱)

这个bug是:
Foreach by reference bug
我今天偶然发现的,汗的是,查看手册发现早就有人提出这BUG,而且到网上一搜发现此BUG的历史还很悠久,可以追溯到2000年的php4.
bug相关链接:
http://bugs.php.net/bug.php?id=29992
http://bugs.php.net/bug.php?id=8373
测试代码:
$a=array('a''b');
foreach($a as &$v){
}
foreach($a as $v){
echo $v;
}

这个BUG真是奇
怪了.
ps:
有人说是trick(陷阱).貌似还是php官方推荐的使用习惯
真是自圆其说呀!
psps:
有搜了一下,原来php团队早就知道这个,但就是不认为是bug.不知道底层的原因是什么,难道和内部机制有关?当是php专有特性吧.小心就是了.



2008-10-8 12:33书中蠹鱼“貌似还是php官方推荐的使用习惯”
这个怎么用?
2008-10-8 12:383227049关键是循环引用后一定要有注销引用的好习惯
比如

$a=array('a','b');
foreach($a as &$v){
}
//unset($v);
$v='c';
print_r($a);
[/code]
这就出问题了


[code]
$a=array('a','b');
foreach($a as &$v){
}
unset($v);//注销引用后这就不是问题的问题
foreach($a as $v){
echo $v;
}


2008-10-8 12:57shitou254$a=array('a','b');
foreach($a as &$v){

}

foreach ($a as $v) {
echo $v;
}
print_r($a); //最后添加这句你会看到 结果的 数组 $a已经被改变了。

第一个循环结束后 $v是个指向数组$a[1] 的 也就是 ‘b’的位置。
当第二个循环开始后 $a as $v第一次执行就是 把 $a 的第一个元素 'a'拷贝给 $v,相当于$v = $a[0] ,所以 $v 就变成了‘a’ ,你忘了在第一个循环结束时候的$v还是指向$a[1]的引用呢,所以成了$a[1] = $a[0],$a就被改变了。$a[1] 被改成 ‘a’ 就成你你看到的接过。


2008-10-8 16:19书中蠹鱼领教了。
2008-10-8 17:42geel那个不是bug,php的foreach就有这个用法
foreach ($arr as &$v) {
$v='another value';
}

foreach ($arr as $key=>$v) {
$arr[$key] = 'another value';
}
哪种简单?
2008-10-17 13:44woodhead31症状对,但楼上解释的不对


$ar = array ( 1,2,3,4);

foreach ($ar as &$item)
{
print_r($item);
}
foreach ($ar as $item)
{
print_r($item);
}
print_r($ar);
?>

如果按照楼上的解释,应该打印
1231才对。但实际上打印的是1233

手册里建议在foreach之后unset($item),确实可以工作。
但这个问题的症状很有趣
2008-10-20 23:33lendy不是bug,针对这个
《php5 Power Programming》
中文《 php5权威编程》 P26有很详细的描述:

foreach($array as [$key =>] [&] $value)

设置&在值前面也是可选的,在你想更改$value的值,并在$array中也生效的时候,你就需要它。



虽然不是指针,但有这个味道。可以理解 引用传递。

6楼 并没有错,只是给你个实例看看,虽然不一定要这么用。


2008-10-21 00:05lendy关于
$ar = array ( 1,2,3,4);

foreach ($ar as &$item)
{
print_r($item);
}
//step 1
foreach ($ar as $item)
{
//step 2
print_r($item);
}
print_r($ar);
?>
的理解:
step 1
$item 应该指向 $ar[3]
然后的循环一直是没变过。
第一次step 2循环,把 $ar[0] 赋值给 $item ,这里 $item 是指向 $ar[3]的,所以$ar[3]=1
第二次step 2循环,把 $ar[1] 赋值给 $item ,这里 $item 是指向 $ar[3]的,所以$ar[3]=2
。。。
第四次的时候
把 $ar[3] 赋值给 $item ,把 $ar[3]在第三次的时候不是已经是3了啊,那不是自己在修改自己,还是3
你可以试试这个


$ar = array ( 1,2,3,4);

foreach ($ar as &$item)
{
print_r($item);

}

foreach ($ar as $item)
{
print_r($item);
break;
}
print_r($ar);
?>

看看是不是1231


你也可以试试step 2的2次循环是不是1232

我觉得你应该好好看看c的指针。


2008-10-21 00:12lendy然后看看这个:


$ar = array ( 1,2,3,4);

foreach ($ar as &$item)
{
print_r($item);
break;
}

foreach ($ar as $item)
{
//step 2
print_r($item); //r1

}
print_r($ar); //r2


?>

r1 和 r2打出来的东西不一样
是在step 2 的第四次循环后才把 $ar[0] 的值给修改了,因为 $item 指向 $ar[0]。
2008-10-21 08:35shitou254还在讨论? 问题就是在第二个循环执行的时候执行了一个指针赋值嘛!
2008-10-21 20:494号HEROIN还是unset最保险
2008-10-31 14:20leicc3、4楼的解释说到点子上了,佩服
到现在发现对引用并不了解
这个是个陷阱,不能算是bug

·发现php的一个BUG.其实都好几年了.有人说是trick(陷阱) | 相关文章·

·百家学院 | 最新评论·