php中unset变量之后只是断开了变量名和变量内容之间的绑定,变量内容并没有被销毁吗?

发布于 2022-09-04 09:57:51 字数 146 浏览 14 评论 0

下列代码执行结果仍为1

<?php
    $a = 1;
    $b =& $a;
    unset($a);
    echo $b;
?>

请问各位大牛,怎么做到真正的清空这段内存?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

网名女生简单气质 2022-09-11 09:57:51

要搞懂这个问题,首先要熟悉PHP底层实现中的两个概念:变量类型和符号表。

在PHP的底层实现,也就是zval中,对PHP的变量类型分为了两种实现形式:对于常规类型,数据的值是直接存储在zval中的;对于对象、数组这类复杂的类型,数据的值是剥离zval,存储在内存的其他地方的,而zval中只存储了那块存储数据的内存地址。

符号表是PHP程序中变量名称和zval值对应关系的存储场所,在PHP底层实现中,是使用HashTable实现的。

在我们unset变量时,实际上PHP只是从符号表里标记清除了这个变量的zval。但由于HashTable是直接存储zval而非引用存储的,所以符号表中所占用的zval内存实际上没有真正释放。当然,在某些对符号表的操作中,可能会触发符号表的自我伸缩,这时候才会真正的对内存进行申请和释放。
另外一方面,如果我们unset的是PHP的复杂类型,除了符号表中的zval外,数据的内容实际上存储在另外一块内存中。对于这种引用类型,PHP都会带有一个refcount引用计数,当zval被清除或者其他操作减少了对象的引用时,变量的引用计数会减一。而如果引用计数为零,则表示变量已经不在PHP程序中被使用了。而对于这类变量,PHP的垃圾回收机制会进行回收并释放那一块的内存。

沧笙踏歌 2022-09-11 09:57:51

在内存堆栈中,a,b只是指向1的引用。只有把指向1的所有引用都销毁掉,才能真正的将1销毁掉。

<?php
    $a = 1;
    $b =& $a;
    unset($a, $b);
    echo $b;
?>

output:

PHP Notice:  Undefined variable: b in /path/to/file/a.php on line 5

Notice: Undefined variable: b in /path/to/file/a.php on line 5

对常量来说,到底是引用还是内存值,我们通过下面的方式来验证:

<?php
    $a = 1;
    $b =$a;
    var_dump($a,$b);
    $a = 2;
    var_dump($a,$b);

?>

输出如下:

int(1)
int(1)
int(2)
int(1)

如果是引用存储的话,那么第二个var_dump输出应该是2,2.

你也可以用debug_zval_dump 这个函数来验证。

参考:http://php.net/manual/zh/function.debug-zval-dump.php

萌能量女王 2022-09-11 09:57:51

这属于底层概念,现代语言大多数都带有垃圾回收机制的。
大多数垃圾回收机制是采用引用计数的来实现的,当你把$a地址引用到$b的时候,这一块内存的引用就会+1。当你在unset($a)的时候代码的引用计数-1。但是并不为0,这代表这块内存还是有别的地方在使用着呢,禁止被回收!

所以在当你没有符号引用$a这段内存的时候,被GC扫描到,这段内存就会被回收了。

不能用c/c++的思想去理解这样的语言,因为很多东西你是不可控的,比如内存管理。


分隔符,如果有新手对楼主的结果有异议的话,可以在线运行一下试试
https://www.bytelang.com/o/s/...

青春如此纠结 2022-09-11 09:57:51

我就贴一下手册 http://php.net/manual/zh/func...

如果在函数中 unset() 一个通过引用传递的变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值
如果在函数中 unset() 一个全局变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文