2

public function evaluateExpression($_expression_,$_data_=array())
    {
        if(is_string($_expression_))
        {
            extract($_data_);
            return eval('return '.$_expression_.';');
        }
        else
        {
            $_data_[]=$this;
            return call_user_func_array($_expression_, $_data_);
        }
    }


我在此方法的第一行收到此错误。我在这里看不到任何打字提示。以上代码来自 Yii Framework 的内部文件。(yiilite.php:L842)

该错误是间歇性的,重新启动 apache 可以修复它。也无法重现错误。什么会导致这个问题?无法弄清楚这一点。

最近要注意的一件事是,此错误仅发生在使用缓存的页面上。早些时候,它会发生在每一页上。

我们正在使用 memcached 和 opcache ( PHP 5.5 )。奇怪的是我们不需要清除 memcached 数据来解决问题,只需要重启 apache,这只会清除“opcache”。

4

1 回答 1

3

错误

您看到的这个错误意味着 PHP 不是在解释阶段失败,而是在执行阶段失败。如您所知,PHP 分两步执行 - 首先,将脚本编译为操作码,然后使用虚拟机(通常是 ZendVM)执行这些操作码。因此我们可以确定它的执行阶段失败的原因在于zend_verify_arg_type(),这是执行实现的一部分:

static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
{
   //I stripped some lines here (insignificant)
   if (cur_arg_info->class_name) {
      /* do the things, when typehinted is class name */
   } else if (cur_arg_info->type_hint) {
      /* your case, typehint wasn't class name */
      switch(cur_arg_info->type_hint) {
           case IS_ARRAY:
               //I stripped some lines here (insignificant)
               break;

           case IS_CALLABLE:
               //I stripped some lines here (insignificant)
               break;

           default: //<---- You error is here
               zend_error(E_ERROR, "Unknown typehint");
       }
   }
   return 1;
}

如您所见,要发生此错误,PHP 应将 typehint 视为非类名,同时将其视为“未知”。这就是为什么你不能在常规情况下重现错误 - 因为 PHP 会首先尝试将 typehint 视为类名(因此,错误将类似于“传递给 {function()} 的参数 {N} 必须是 {classname 的实例}" )

原因

所以,虽然在正常的执行机制中你不会得到这样的错误,你仍然可以得到一些损坏的编译文件——另一个提示是你正在使用 opcache。因此,这可能是因为您正在评估方法中的某些代码,这可能会导致编译文件损坏 - 但我不能肯定地说。另一件事-它可能是内部opcache扩展的错误。但无论如何,原因是 - 当VM尝试执行已编译的脚本时,错误的编译会导致此类错误。而且,因为它可以通过清除 opcache 来解决(所以,网络服务器重新启动) - 我认为原因是 - 这是一个错误。

所以,TL;DR - 我不能肯定地说出原因,但可以给出一些指导。由于这对于仅发表评论来说太多了,因此发布作为答案

于 2014-08-25T14:09:32.167 回答