PHP的”Allowed memory size”错误的深入理解

PHP的”Allowed memory size”错误的深入理解

以前追踪过这个问题,但是那个时候工具用的不太好,没看的这么细,这次搞的比较细,修正了偶以前的看法.于是写小文一篇总结一下.

PHP偶尔会爆一下如下 错误Allowed memory size of xxx bytes exhausted at xxx:xxx (tried to allocate xxx bytes)

不想看原理的,直接跳到最后看总结.

这个报错信息的意思是是说,若ini配置的memory_limit(内存限制) 大于 AG(allocated_memory),就报错

AG(allocated_memory) += rs;

if (AG(memory_limit)<AG(allocated_memory)) {

int php_mem_limit = AG(memory_limit);

AG(allocated_memory) -= rs;

if (EG(in_execution) &#038;& AG(memory_limit)+1048576 > AG(allocated_memory)){

AG(memory_limit) = AG(allocated_memory) + 1048576;

if (file) {

zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted

at %s:%d (tried to allocate %d bytes)", php_mem_limit, file, lineno, s);

} else {

zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted

(tried to allocate %d bytes)", php_mem_limit, s);

}

} else {

if (file) {

fprintf(stderr, "Allowed memory size of %d bytes exhausted

at %s:%d (tried to allocate %d bytes)n", php_mem_limit, file, lineno, s);

} else {

fprintf(stderr, "Allowed memory size of %d bytes exhausted

(tried to allocate %d bytes)n", php_mem_limit, s);

}

exit(1);

}

}

memory_limit很简单,就是PHP可用的内存..AG(allocated_memory)是什么呢?是不是已经使用的内存,恩,我们用代码验证一下

PHP_FUNCTION(memory_get_usage) {

RETURN_LONG(AG(allocated_memory));

}这下就清晰明了,还不懂的,查php手册,看memory_get_usage的说明

到底什么时候设置AG(allocated_memory)呢,具体代码就不贴了,太繁琐,是在emalloc函数中调用了第一段代码,看第一行代码,那里的rs就是每次tried to allocate %d bytes对应的s变量(你要申请的实际空间)的align对齐,具体计算方法:rs = (s+7) & ~0x7,也就是必须是8的倍数,不足则补足,这样做的好处是符合64位机器的要求,可以加速运算,例如 s =1,那么运算出来的rs =8 ,具体的,可以自己用PHP写个函数计算(0×7是16进制写法).

总结:既然知道了怎么回事,就好解决了,在开启 –enable-memory-limit情况下,会出这个错误,把配置文件直接设置memory_limit,或者在代码中设置ini_set(’memory_limit’, ‘value’)都可以,省事的办法就是设置配置文件(如php.ini)

而且建议开启–enable-memory-limit,若这个不开启,PHP的内存限制就处于”裸跑”状态,可能会出现著名的out of memory错误.