memory_limit的一个bug | 风雪之隅

简介: 原文:memory_limit的一个bug | 风雪之隅 27 Nov 09 memory_limit的一个bug 作者: Laruence( ) 本文地址: http://www.
原文: memory_limit的一个bug | 风雪之隅

27 Nov 09 memory_limit的一个bug

PHP 5.2x中, 由于错误的选用了zend_atoi, 导致memory_limit不能设置为超过4G的值.

今天同事分享给我一个问题(thans to yanmi), 一段代码(PHP 5.2.11 Linux/X86_64),设置memory_limit为4096M会导致内存耗尽, 而设置4095M就不会. 奇怪的问题呵.

那是怎么回事呢?

问题的原因也很简单, 在PHPSRC/main.c中定义的memory_limit设置项的处理器OnChangeMemoryLimit中, 并没有检测当前的机器字长, 而统一使用了zend_atoi来做为字符串数字化, 这个问题在PHP5.3的版本中已经修正(换成了zend_atol):

 
 
  1. static PHP_INI_MH(OnChangeMemoryLimit)
  2. {
  3.     if (new_value) {
  4.         PG(memory_limit) = zend_atoi(new_value, new_value_length);
  5.     } else {
  6.         PG(memory_limit) = 1<<30; /* effectively, no limit */
  7.     }
  8.     return zend_set_memory_limit(PG(memory_limit));
  9. }

而, 顾名思义么, atoi是转成整形, 4096M是2的32次方, 发生溢出, 继而环绕成结果为0, zend_atoi代码如下:

 
 
  1. ZEND_API int zend_atoi(const char *str, int str_len)
  2. {
  3.     int retval;
  4.  
  5.     if (!str_len) {
  6.         str_len = strlen(str);
  7.     }
  8.     retval = strtol(str, NULL, 0);
  9.     if (str_len>0) {
  10.         switch (str[str_len-1]) {
  11.             case 'g':
  12.             case 'G':
  13.                 retval *= 1024;
  14.                 /* break intentionally missing */
  15.             case 'm':
  16.             case 'M':
  17.                 retval *= 1024;
  18.                 /* break intentionally missing */
  19.             case 'k':
  20.             case 'K':
  21.                 retval *= 1024;
  22.                 break;
  23.         }
  24.     }
  25.     return retval;
  26. }

最后在zend_set_memory_limit的时候, 会错误的设置memory_limit为mm_heap的blok_size, 那结果就肯定远远小与你所预期的4096M了

 
 
  1. ....
  2.  AG(mm_heap)->limit = (memory_limit >= AG(mm_heap)->block_size) ? memory_limit : AG(mm_heap)->block_size;
  3. ...

最后, 如果是32位的机器, 那确实不算bug, 但现在的机器很多都64了, 最大内存也不再是4GB了, PHP也要与时俱进啊.

PS, 多看别人的代码是有好处的, 今天有学会了intentionally这个单词, ^_^.


分享到: 1



Related Posts:

Tags: PHP, php bug, php源码分析

目录
相关文章
|
8月前
|
监控 数据处理 算法框架/工具
Allocation of 179437568 exceeds 10% of free system memory.
本文讨论了在Python编程中遇到的"Allocation of XXXX exceeds 10% of free system memory"错误,并提供了几种解决方法,包括调整代码逻辑以减少内存分配和更改批量大小。
|
存储 缓存 大数据
Starrocks执行查询报错:Memory of process exceed limit. Used: XXX, Limit: XXX. Mem usage has exceed the limit of BE
Starrocks执行查询报错:Memory of process exceed limit. Used: XXX, Limit: XXX. Mem usage has exceed the limit of BE
|
11月前
|
Java 编译器 iOS开发
8 种 Java 内存溢出之七 -Requested array size exceeds VM limit
8 种 Java 内存溢出之七 -Requested array size exceeds VM limit
|
11月前
|
Java 开发者 iOS开发
8 种 Java- 内存溢出之二 -GC overhead limit exceeded
8 种 Java- 内存溢出之二 -GC overhead limit exceeded
|
存储 算法 Java
JEP 331: Low-Overhead Heap Profiling
JEP 331: Low-Overhead Heap Profiling
161 1
|
Docker 容器
解决Native memory allocation (mmap) failed to map 2060255232 bytes for committing reserved memory.
解决Native memory allocation (mmap) failed to map 2060255232 bytes for committing reserved memory.
1676 0
|
前端开发 API PHP
php内存溢出:Allowed memory size of 1342bytes exhausted (tried to allocate 8192 bytes)本地配置和宝塔配置解决方案
php内存溢出:Allowed memory size of 1342bytes exhausted (tried to allocate 8192 bytes)本地配置和宝塔配置解决方案
200 0
|
Oracle Java 关系型数据库
GC Overhead Limit Exceeded Error
GC Overhead Limit Exceeded Error
223 0
JVM 报 GC Overhead limit exceeded 是什么意思?
JVM 报 GC Overhead limit exceeded 是什么意思?
Using 1 worker with 2048MB memory limit 异常
这里使用的是node 16版本,在家里电脑可以,但是公司电脑不行,不知道为啥 最后换了14版本,就可以了。
2040 0
Using 1 worker with 2048MB memory limit 异常