? ? ? ?有個寫的腳本是crontab每分鐘運(yùn)行一次的阿迈,后來發(fā)現(xiàn)腳本運(yùn)行有問題,于是查找log。log顯示腳本一分鐘運(yùn)行一次是沒問題的,但有時出現(xiàn)Fatal Error => Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)症杏。
? ? ? ?瞬間認(rèn)為是memory_limit 參數(shù)的設(shè)置問題,于是果斷ini_set設(shè)置memory_limit為512M瑞信。提交后查看log厉颤,發(fā)現(xiàn)依舊有這個錯誤。這就比較尷尬了凡简,我回憶了下memory_limit的錯誤提示逼友,好像確實(shí)不是這個,那就百度一下吧秤涩。
? ? ? ?經(jīng)過一陣百度帜乞,關(guān)于這個錯誤有答案的回答都建議ini_set('limit_memory','1024M'),或者是在php.ini設(shè)置linit_memory重啟。那這就又尷尬了筐眷。黎烈。。匀谣。沒辦法照棋,我只能
cd php-5.5.13/Zend;
grep "Out of memory" -R -n .
定位到了zend_alloc.c的第1992行和第2304行。
第一個函數(shù)是 _zend_mm_alloc_int 第二個函數(shù)是 _zend_mm_realloc_int武翎×姨浚看名字這兩個函數(shù)是分配內(nèi)存的。接著定位到下面這一段宝恶。
//當(dāng)real_size (Zend 已經(jīng)分配的內(nèi)存大小) segment_size(這次要分配的segment的大小) 加起來大于 heap->limit
//報 Allowed memory size 錯誤符隙,這里 heap->limit 參數(shù)就是設(shè)置的memory_limit
if (segment_size < true>real_size + segment_size > heap->limit) {
/* Memory limit overflow */
#if ZEND_MM_CACHE
zend_mm_free_cache(heap);
#endif
HANDLE_UNBLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->li
mit, __zend_filename, __zend_lineno, size);
#else
zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size
);
#endif
}
segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size);
//這里當(dāng)上一步的 ZEND_MM_STORAGE_ALLOC失敗 會報Out of memory錯誤
//ZEND_MM_STORAGE_ALLOC宏 define ZEND_MM_STORAGE_ALLOC(size) heap->storage->handlers->_alloc(heap->storage, size)
//storage在存儲層的操作,相關(guān)資料->看這里 http://www.phppan.com/2010/11/php-source-code-30-memory-pool-storage/
//這里就是malloc啦 malloc失敗
if (!segment) {
/* Storage manager cannot allocate memory */
#if ZEND_MM_CACHE
zend_mm_free_cache(heap);
#endif
out_of_memory:
HANDLE_UNBLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __ze
nd_filename, __zend_lineno, size);
#else
zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
#endif
return NULL;
}
兩種錯誤提示:
? ? ? ?1.當(dāng)segment_size < true>real_size + segment_size > heap->limit 時趴捅, heap->limit就是memory_limit的值,如果要用的內(nèi)存比它大膏执, 會報Allowed memory size of .....,
? ? ? ? 2.如果沒有超過設(shè)定的limit驻售,接著ZEND_MM_STORAGE_REALLOC分配segment,當(dāng)!ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size)時更米,會報Out of memory欺栗。 分配失敗,報Out of memory錯誤征峦。
這里是malloc失敗迟几,那么是不是服務(wù)器做了什么限制呢,我沒有權(quán)限登錄這臺服務(wù)器栏笆。于是發(fā)信去問类腮,各種問過后發(fā)現(xiàn)是ulimit限制在125M。修改大后錯誤消失蛉加。
一些參考