Reference detection in array from another function

前端 未结 3 1248
轻奢々
轻奢々 2021-01-02 05:11

So I\'m using the pin method, but the reference is detected one level too late:

$pin = time();

function wrap($arr){
  test($arr);
}

function test(&$arr         


        
3条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-02 05:35

    function wrap($arr){ test($arr); }
    /// ...
    wrap($array);
    

    Your wrap() function allocates new memory block for $arr. When you calling test() function within wrap()s body, it takes reference of $arr memory block, but not an $arrays memory block, because $arr is a copy of $array and PHP memory management system stores them separately.


    There is a universal reference spotting function:

    function is_equal_refs(&$a, &$b){
        $buffer = $a;          // saving current value in temporary variable
    
        $a = md5(time());      // assigning new value to memory block, pointed by reference
    
        $result = ($a === $b); // if they're still equal, then they're point to the same place.
    
        $a = $buffer;          // restoring value
    
        return $result;        // returning result
    }
    

    So, lets do some testing:

    
    

    Shows:

    1   // < $arr
    2
    3
    1   // < $array
    2
    3
    ref // < $array doubled -> reference found
    

    The reason of such behavior is $arr[3] contains reference for $arrays memory block, but not reference of itself's memory block.

    Lets remove a $array[] = &$array; row, and modify wrap() function to check:

    function wrap($arr){
        $arr[] = &$arr;
    
        test($arr);
    }
    

    And result would be:

    1   // < $arr
    2
    3
    ref // < $arr doubled -> reference found
    

    Because $arr not points to $array, but to itself in $arr[3]. So, in your code there are different references you want to spot.


    CONCLUSION: What you want to achieve is breaking out PHP memory management rules.


    UPDv1:

    Need to seek a workaround, to restore $array reference in a wrap() function scope.

    1) A "bad" / "globals" practice:

    
    

    Which shows:

    1
    2
    3
    ref
    

    2) A "wrap everything in array or object" practice: (prefered and reliable)

     &$array)); // trick
    
    print PHP_EOL;
    
    $ring      = array(1, 2, 3, array(4, 5, 6));
    $ring[3][] = &$ring;
    
    wrap(array(REF_MARKER => &$ring)); // trick
    
    print PHP_EOL;
    
    $test = array('a', 'b', 'c');
    $ring = array(1, 2, 3);
    
    $ring[] = &$test;
    $test[] = &$ring;
    
    wrap(array(REF_MARKER => &$ring)); // trick
    
    print PHP_EOL;
    
    wrap(range(1, 5)); // normal
    
    print PHP_EOL;
    
    $test = array(1, 2, 3, array(1, 2, 3), 4, array(5, 2, 3), array(6, array(1, 2, 3), 7), array(1, 2, 3));
    
    wrap($test); // normal
    
    print PHP_EOL;
    
    $test[]    = &$test;
    $test[3][] = &$test;
    $test[5][] = &$test[3];
    
    wrap(array(REF_MARKER => &$test)); // trick
    ?>
    

    Shows:

    1 2 3 ref
    1 2 3 4 5 6 ref
    1 2 3 a b c ref
    1 2 3 4 5
    1 2 3 1 2 3 4 5 2 3 6 1 2 3 7 1 2 3
    1 2 3 1 2 3 ref 4 5 2 3 ref 6 1 2 3 7 1 2 3 ref
    

提交回复
热议问题