The variable refers to itself
Asked Answered
U

1

23

I read a lot of articles about how to construct the variables inside the machine Zend and found one interesting thing that I can not explain:

$int = 100;
xdebug_debug_zval('int'); /// int:(refcount=1,is_ref=0),int 100
$int = &$int;
xdebug_debug_zval('int'); /// int:(refcount=1,is_ref=1),int 100

As it turns out that we are creating the link itself to itself? How is it possible?

Clear information from what I know:

As a rule is_ref = 1 only when the container refers zval two or more variables of hard link.

refcount - is the number of variables refer to the same zval container, but the difference is that the refcount for different works with is_ref = 0 and is_ref = 1.

If is_ref = 0, and refcount > 1 when creating hard links, we get a new zval container, if we do the assignment by a value - new zval container will not be created.

If is_ref = 1, and refcount > 1 when creating hard links new zval is not created, used old. if we do not create a hard link, but do assigning by a value - it means what we created new zval container.

P.S I wrote this in order to show that understand that I ask and show why I do not understand the behavior of the code that I have written above

Unthread answered 26/10, 2016 at 19:9 Comment(13)
@RyanVincent Is this possible? How can I make a hard link to the same variable, ie itselfUnthread
@RyanVincent I dont understand you. I know what a variable have own a zval containerUnthread
maybe interesting? PHP5 References Explained Visually. Later and easier to understand.Mellophone
@RyanVincent I read your manual. But i didn't get answer on my evil question - $int = &$int - what the ??? is this?Unthread
@RyanVincent But in my case it doesn't increase refcount, she still yet is 1Unthread
@RyanVincent I honestly do not understand what happens when I make a reference on itselfUnthread
@RyanVincent how, if we have a single copy variable that refers to this zval container?Unthread
@RyanVincent I read this material to understand your articles, I'm just not true written declaration of my post due to the fact that I used the google translator for translation assistance.Unthread
@RyanVincent Just could you explain step by step what is happening here:$a = 10; $b = &a; And here $a = 10; $a = &$a; ThanksUnthread
Read this stuff first: References Explained. Then come back if you are still confused. I really suggest working through a model made of bits of paper for the various parts. It slows down your thinking and allows you to check your assumptions.Mellophone
@RyanVincent I've read this php.net/manual/en/language.references.php too.Unthread
Let us continue this discussion in chat.Unthread
@Unthread What question has still not been answered that you put up a new bounty? (Be precise please)Dormie
B
10

The answer is pretty simple, as explained in the comments to your question. Though, I think I understand where your confusion comes from, so let's break this down. :D

First you assign a value to a variable, internally PHP stores this in a memory segment and increases the counter of variables which refers to this address. (Ref count = 1). All straight forward up until this point.
Then, you re-use the variable to store a reference (pointer in C-terms) to this memory address. The PHP manual explains this as storing a reference to a variable, to make things easier for non-C programmers, which is where (I think) your confusion comes from. There is no such thing as a reference to a variable in the internals, just the data the variable is linked to. Since you re-used the variable to store this reference, the reference count doesn't increase: There is still just one variable pointing to this memory segment. However, it is no longer a normal PHP variable, but a reference (pointer) to the data.

Edit, added:
Another way to accomplish the same result, is by using two variables and then unset the first one. Code example:

$a = 100; // refcount += 1
xdebug_debug_zval ('a'); // refcount=1,is_ref=0 -> zval {value=100,type=int (addr=0x78765asd)}

$b =& $a; // refcount += 1
xdebug_debug_zval ('a') // refcount=2,is_ref=0 -> zval {value=100,type=int (addr=0x78765asd)}
xdebug_debug_zval ('b') // refcount=2,is_ref=1 -> zval {value=100,type=int (addr=0x78765asd)}

unset ($a); // refcount -= 1
xdebug_debug_zval ('b') // refcount=1,is_ref=1 -> zval {value=100,type=int (addr=0x78765asd)}

Using only one variable merges the two operations into one, without destroying the data. Thus: 1 variable (refcount=1), which is a reference (is_ref=1) to the data itself.

As we've tried to explain to you the confusion stems from the fact that the premise behind the original question is flawed: You're not referencing a variable in these examples, you're referencing an area of memory which contains the data originally associated with said variable. So you're overwriting one (the original) "hardlink", with another. Only difference is that the latter is marked as such, for internal PHP reasons. (References does not get copied on write, in the case of refcounts > 1.)

Brisbane answered 1/11, 2016 at 7:18 Comment(10)
If I understand you correctly that: No referenced concepts such type of data in php, there is only variable that stores a pointer to a zval container. But if this is the case then there is no special variables in php and breaks your concept to smithereensUnthread
What kind of special variables are you thinking of?Brisbane
@Unthread I've updated my answer to explain it in a slightly different, and hopefully clearer way, for you.Brisbane
You have a mistake. Last line // refcount=1,is_ref=1 -> zval {value=100,type=int (addr=0x78765asd)} - I tested it! is_ref=0Unthread
It was you who said that there were "special variables" in PHP, I simply asked you for a clarification on what you meant were "special variables." That said, seeing as you're unwilling to accept any explanation that goes against what you perceive to be correct, I'm afraid I cannot help you further. I wish you the best of luck forward.Brisbane
So in C, $a = &$a; is like a =& *a;?Bollinger
@PEMapModder I'm not 100% fluent in C, as it's been years since I last worked with it, but.. Yeah, should be basically the same. IIRC.Brisbane
@Brisbane I could not answer for a long time because I had no time. You said what: "Thus: 1 variable (refcount=1), which is a reference (is_ref=1) to the data itself." - what does it mean? If we write $int = &$int; what will difference from simple $int = 10;? How you wrote, variable references on zval container. What will be difference simple variable from variable which reference itself, it is same zval container. I am confusing. SOSUnthread
@Brisbane Are you here?Unthread
@Unthread Sorry for the late reply, been away. Effectively there is no difference between the two, other than the flag being set. That flag only has an effect when there are two, or more, refcounts. In other words: If two variables are pointing at the same ZVAL, and one of them has the is_ref flag set, the ZVAL won't be copied on write as per usual. Seems like unset() handles this by removing the flag, which is why the example I posted above was slightly wrong.Brisbane

© 2022 - 2024 — McMap. All rights reserved.