【问题标题】:Using reference to nonexistent value sets variable to NULL?使用对不存在值的引用将变量设置为 NULL?
【发布时间】:2011-05-21 18:40:34
【问题描述】:

当通过引用传递一个不存在的值时,PHP 会创建该值并将其设置为 NULL。当在某些函数中检查空值时发生内存增加时,我注意到了这一点。取如下函数:

function v(&$v,$d=NULL){return isset($v)?$v:$d;}
$bar = v($foo, $default);

这将是以下的简写:

if(isset($foo))
{
    $bar = $foo;
}
else
{
    $bar = $default;
}

但是,当传递不存在的变量时,PHP 会创建它们。在变量的情况下 - 一旦方法/函数结束它们就会被删除 - 但对于检查超级全局数组,如 $_GET 或 $_POST 数组元素永远不会被删除,从而导致额外的内存使用。

$request_with = v($_SERVER['HTTP_X_REQUESTED_WITH']);

谁能解释为什么会发生这种情况,以及它是 PHP 待办事项修复还是其他一些疯狂使用值的功能?

【问题讨论】:

  • 在 Debian、Ubuntu 和 Windows XP 上运行 PHPFastcgi 的 PHP 5.3.x。

标签: php variables null


【解决方案1】:

你有内存泄漏的原因,是因为你告诉它。

当您要求参考参数时,PHP 会为您提供一个。当您使用未设置的变量调用函数时,PHP 将设置该变量,然后将引用传递给该新变量。当您使用超全局调用它时,它会创建缺失的索引。那是因为你告诉了它。

但是,我必须问为什么您需要变量引用? 99.9% 的时间你并不真正需要它们。我怀疑这样做会很好:

function v($v, $d = null) { return isset($v) ? $v : $d; }

或者,如果您确实必须使用引用(您无法解决原来的问题),您还应该返回一个引用:

function &v(&$v, $d = null) { 
    if (isset($v)) {
        return $v;
    }
    return $d;
}

否则取一个引用而不返回一个是没有意义的......

【讨论】:

  • 确实毫无意义。我唯一的猜测是他认为他通过不传递价值来节省资源。不幸的是,他不知道 COW(写时复制)。
  • 我知道 COW,节省内存不是功能的重点。处理不存在的值是。但是,function &v(){...} 是无效的 PHP:Notice: Only variable references should be returned by reference,这就是它写成这样的原因。换句话说,引用是处理未设置值而不导致 PHP 出错的唯一方法。
【解决方案2】:

XeonCross 的函数 v 是常用的简写:

$val= isset($arr['elm']) ? $arr['elm'] : 'default'

为了避免可怕的“未定义索引:榆树”通知。一个不错的辅助函数是:

function ifset(&$v1, $v2 = null) {
    return isset($v1) ? $v1 : $v2;
}

正如 Xeoncross 建议的那样,你可以写得更好

$val = ifset($arr['elm'],'default') 

然而,这在我们钟爱的我们称之为 PHP 的“语言”中有很多有趣的(?)怪癖:

在 ifset 函数内部,$v1 似乎是 UNSET,因此它正确返回值 $v2,您可能会得出结论 ifset 工作正常。但之后 $arr['elm'] 被静默设置为 NULL。所以考虑以下几点:

    function wtf(&$v) {
       if (isset($v))
           echo "It is set";
       else
           echo "It is NOT set";
    }
    $p=[];
    wtf($p['notexist']);   => It is NOT set
    $p;                    => [ 'notexist' => NULL ]

但这是另一个错觉,因为 isset() 函数也会为 NULL 值返回 false:

$x=NULL;
isset($x)   => false... huh??

我们是否预料到了这一点?好吧..它在文档中,所以这也是设计使然。欢迎来到美妙的 php 世界。

【讨论】:

  • 我还创建了一个与此完全相同的方法。然后我花了半天的时间试图弄清楚是什么在我的数组中创建了糟糕的数据。 ://
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
相关资源
最近更新 更多