php对内存的管理机制相当的详尽,它在这一点上更类似与java的垃圾回收机制。而对于c语言或者c++大部分时候都只能由程序员自己把申请的空间释放掉。在php中,由于要应对成千上万的连接,同时这些连接往往还需要保持很长的时间。这并不同于c中程序结束了相应的内存块就会被回收。
所以仅仅依靠程序员在写程序的时候注意内存回收是不够的,php肯定要有一些自己内部的、与连接相关的内存管理机制来保证不发生任何的内存泄露。
在本文中,首先对php的内存机制进行一个介绍:
那些在c语言中的空间函数,比如malloc() free() strdup() realloc() calloc(),php中会有不同的形式。
简介PHP轻论坛是一个简单易用的PHP论坛程序,适合小型社区和个人网站使用。v3.0版本是完全重构的版本,解决了之前版本中的所有已知问题,特别是MySQL保留字冲突问题。主要特点• 简单易用:简洁的界面,易于安装和使用• 响应式设计:适配各种设备,包括手机和平板• 安全可靠:避免使用MySQL保留字,防止SQL注入• 功能完善:支持分类、主题、回复、用户管理等基本功能• 易于扩展:模块化设计,便于
21
返还申请的内存:对于程序员来说,每一块申请的内存都应该返还,如果不还就会导致内存泄漏。在那些不要求一直运行的程序中,稍许的内存泄漏在整个进程被杀掉之后就结束了。但是类似于apache这种一直运行的web server,小的内存泄漏最终会导致程序的崩溃。
错误处理的例子:
立即学习“PHP免费学习笔记(深入)”;
在进行错误处理的时候,采用的机制一般是是Zend Engine会设定一个跳出地址,一旦发生exit或die或任何严重错误E_ERROR的时候,就会利用一个longjmp()跳到这个地址上面去。但是这种做法几乎都会导致内存泄漏。因为free的操作都会被跳掉。(这个问题在c++里面也同样存在,就是在设计类的时候,绝不要把错误处理或告警函数写在构造或者析构函数内,同样的原因,由于对象已经处在了销毁或创建的阶段,所以任何错误函数处理都可能打断这一过程,从而可能导致内存泄漏。) 下面的代码中就给出了这样的一个例子:void call_function(const char *fname, int fname_len TSRMLS_DC)
{
zend_function *fe;
char *lcase_fname;
/* PHP function names are case-insensitive to simplify locating them in the function tables all function names are implicitly
* translated to lowercase
*/
lcase_fname = estrndup(fname, fname_len);//创造一个函数名的副本
zend_str_tolower(lcase_fname, fname_len);//都转换成小写,这样的寻找的时候很方便,这应该也是php函数表中进行函数标识的方式。
if (zend_hash_find(EG(function_table),
lcase_fname, fname_len + 1, (void **)&fe) == FAILURE) {?SUCCESS。这个是要在函数表里面寻找待调用的函数。
zend_execute(fe->op_array TSRMLS_CC);
} else {
php_error_docref(NULL TSRMLS_CC, E_ERROR,
"Call to undefined function: %s()", fname); //等同于Trigger_error()
}
efree(lcase_fname);
}
* {
* zval *helloval;
* MAKE_STD_ZVAL(helloval);
* ZVAL_STRING(helloval, "Hello World", 1);
* zend_hash_add(EG(active_symbol_table), "a", sizeof("a"),
* &helloval, sizeof(zval*), NULL);
* zend_hash_add(EG(active_symbol_table), "b", sizeof("b"),
* &helloval, sizeof(zval*), NULL);
* }
* {
* zval *helloval;
* MAKE_STD_ZVAL(helloval);
* ZVAL_STRING(helloval, "Hello World", 1);
* zend_hash_add(EG(active_symbol_table), "a", sizeof("a"),
* &helloval, sizeof(zval*), NULL);
* <strong>ZVAL_ADDREF(helloval);</strong>//加上这个之后,就不会有重新释放同一块内存空间这样的错误了
* zend_hash_add(EG(active_symbol_table), "b", sizeof("b"),
* &helloval, sizeof(zval*), NULL);
* }
<?php
$a = 1;
$b = $a;
$b += 5;
?>zval *get_var_and_separate(char *varname, int varname_len TSRMLS_DC)
{
zval **varval, *varcopy;
if (zend_hash_find(EG(active_symbol_table),
varname, varname_len + 1, (void**)&varval) == FAILURE) {
/*符号表里没找到 */
return NULL;
}
if ((*varval)->refcount < 2) {
/* varname 是唯一的引用,什么也不用做 */
return *varval;
}
/* 否则的话,不是唯一的引用,给zval*做一个副本 */
MAKE_STD_ZVAL(varcopy);
varcopy = *varval;
/* Duplicate any allocated structures within the zval* */
zval_copy_ctor(varcopy); //这一块是怎么拷贝的?mark 应该已经跟varval对应的varname连起来了
/* 把varname的版本删掉,这会减少varval的引用次数 */
zend_hash_del(EG(active_symbol_table), varname, varname_len + 1);
/* 初始化新创造的值的引用次数,然后附给varname变量 */
varcopy->refcount = 1;
varcopy->is_ref = 0;
zend_hash_add(EG(active_symbol_table), varname, varname_len + 1,
&varcopy, sizeof(zval*), NULL);
/* Return the new zval* */
return varcopy;
}<?php
$a = 1;//执行完这一句之后,a变量的ref_count是1,is_ref是0
$b = &$a;//这一句之后,变量(zval*)的ref_count是2,然后由于显示的&,is_ref为1
$b += 5;// 这个时候在执行这一句的时候就不会有任何的分离
?>if ((*varval)->is_ref || (*varval)->refcount < 2) {
/* varname is the only actual reference,
* or it's a full reference to other variables
* either way: no separating to be done
*/
return *varval;
}<?php
$a = 1;
$b = $a;
$c = &$a;
?>
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号