array_merge_recursive - мистика или ...

camka

не самка
array_merge_recursive - мистика или ...

Данный кусочек кода не дает мне покоя уже второй день
PHP:
<?php

$c=array('a' => 'aa','b' => 'bb');
$d=array('a' => 'aa','b' => 'bb');

$a=$c;
$b=$c;

$f=array_merge_recursive($a,$b);
var_dump($f);

$e=array_merge_recursive($c,$d);
var_dump($e);

?>
----
Простите, изменил $d на $e
---
на строке $f=... вылазит ошибка
Warning: array_merge_recursive(): recursion detected in ...
и вар_дамп дает
PHP:
array
  'a' => 'aa'
  'b' => 'bb'
строка же $d=... выполняется без проблем
вар_дамп дает
PHP:
array
  'a' => 
    array
      0 => 'aa'
      1 => 'aa'
  'b' => 
    array
      0 => 'bb'
      1 => 'bb'
этот же дамп я ожидаю и в первом случае, по тому что он логически верен.

Почему вылазит ворнинг?

Кстати на пхп 4.2.2 ворнинга нету и первый дамп верный. Я юзаю 4.3.2 на виндозе. Подобная же лажа наблюдается и на 4.3.1

Кроме того если после строки $a=$c; добавить к $a новый элемент, примерно так
PHP:
$a['c']='c';
, то бага не пропадает.
Я чего-то недоглядел?
 

camka

не самка
Подобная же ошибка вылазит при тривиальном
PHP:
$u = array('a'=>'fff');
array_merge_recursive($u,$u);
если массив не ассоциативный то все работает.
 

Profic

just Profic (PHP5 BetaTeam)
Код:
while (zend_hash_get_current_data_ex(src, (void **)&src_entry, &pos) == SUCCESS) {
  switch (zend_hash_get_current_key_ex(src, &string_key, &string_key_len, &num_key, 0, &pos)) {
  case HASH_KEY_IS_STRING:
    if (recursive && zend_hash_find(dest, string_key, string_key_len, (void **)&dest_entry) == SUCCESS) {
      if (*src_entry == *dest_entry) {
        zend_error(E_WARNING, "%s(): recursion detected",
        get_active_function_name(TSRMLS_C));
        return 0;
      }
      SEPARATE_ZVAL(dest_entry);
      convert_to_array_ex(dest_entry);
      convert_to_array_ex(src_entry);
      if (!php_array_merge(Z_ARRVAL_PP(dest_entry), Z_ARRVAL_PP(src_entry), recursive TSRMLS_CC)) return 0;
    } else {
      (*src_entry)->refcount++;
      zend_hash_update(dest, string_key, strlen(string_key)+1, src_entry, sizeof(zval *), NULL);
      }
    break;
  }
}
Вот кусок исходника, который собственно этим и занимается.
1) Zend Optimizer случаем не включен?
2) Исходя из приведенного исходника engine оптимизирует присвоение массива не как копирование, а как присвоение ссылки, что и приводит к появлению ошибки... Это опять же очень похоже на Zend Optimizer...
 

Profic

just Profic (PHP5 BetaTeam)
А насчет последнего, - так и не выйдет...
if (*src_entry == *dest_entry) {
не даст объединить два одинаковых массива если в них есть хоть один сроковый ключ...
 

camka

не самка
зенд оптимайзера не пользуем. Начал было грешить на Xdebug, однако после отключения оного глюк остался.
 

camka

не самка
Автор оригинала: Profic
А насчет последнего, - так и не выйдет...
if (*src_entry == *dest_entry) {
не даст объединить два одинаковых массива если в них есть хоть один сроковый ключ...
А теоретически вполне возможно
 

Profic

just Profic (PHP5 BetaTeam)
зенд оптимайзера не пользуем. Начал было грешить на Xdebug, однако после отключения оного глюк остался.
Хм. Тогда остается, только одно предположение... Zend-овцы чего-то нахимичили с оптимизацией присвоения в 4.3.0...
По bugs.php.net искать не пробовал?
 

camka

не самка
искал - не нашел, есть баги связанные с array_merge_recursive, но аналогичного что-то не видать. Может плохо искал.
 

Profic

just Profic (PHP5 BetaTeam)
А теоретически вполне возможно
Дык понятно, что можно :) - будем звать кодеров PHP химиками :)
Блин такое не работает :(
PHP:
<?php 

$c = array ('a' => 'aa', 'b' => 'bb'); 
$d = array ('a' => 'aa', 'b' => 'bb', 'c' => 'cc'); 

echo '<pre>';

$a = array_merge ($c, array ());
$a['c'] = 'cc';
$b = $c; 

$f = array_merge_recursive ($a, $b); 
var_dump ($f); 
echo '</pre>';

?>
 

Profic

just Profic (PHP5 BetaTeam)
искал - не нашел, есть баги связанные с array_merge_recursive, но аналогичного что-то не видать. Может плохо искал.
Я тоже не нашел... Может это и бага, а может это я сегодня туплю...

По моему ИМХО та функция написана, как-то странно :)
 

camka

не самка
Ну дак что ж? Отписаться может в баг-репорте тогда, или же подождать уважаемых гуру для принятия окончательного решения?
 

Profic

just Profic (PHP5 BetaTeam)
Гуру, чего-то не откликаются, отпиши баг репорт....
 

camka

не самка
Странное поведение функции оказалось самым что ни на есть обычным багом. Вот тут http://bugs.php.net/24198 чистосердечное признание в этом самих разработчиков.
спасибо всем кто принимал участие в дискуссии.
 
Сверху