? ? ? ?有個(gè)寫的腳本是crontab每分鐘運(yùn)行一次的,后來發(fā)現(xiàn)腳本運(yùn)行有問題,于是查找log。log顯示腳本一分鐘運(yùn)行一次是沒問題的,但有時(shí)出現(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)依舊有這個(gè)錯(cuò)誤。這就比較尷尬了,我回憶了下memory_limit的錯(cuò)誤提示,好像確實(shí)不是這個(gè),那就百度一下吧。
? ? ? ?經(jīng)過一陣百度,關(guān)于這個(gè)錯(cuò)誤有答案的回答都建議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行。
第一個(gè)函數(shù)是 _zend_mm_alloc_int 第二個(gè)函數(shù)是 _zend_mm_realloc_int??疵诌@兩個(gè)函數(shù)是分配內(nèi)存的。接著定位到下面這一段。
//當(dāng)real_size (Zend 已經(jīng)分配的內(nèi)存大小) segment_size(這次要分配的segment的大小) 加起來大于 heap->limit
//報(bào) Allowed memory size 錯(cuò)誤,這里 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失敗 會(huì)報(bào)Out of memory錯(cuò)誤
//ZEND_MM_STORAGE_ALLOC宏 define ZEND_MM_STORAGE_ALLOC(size) heap->storage->handlers->_alloc(heap->storage, size)
//storage在存儲(chǔ)層的操作,相關(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;
}
兩種錯(cuò)誤提示:
? ? ? ?1.當(dāng)segment_size < true>real_size + segment_size > heap->limit 時(shí), heap->limit就是memory_limit的值,如果要用的內(nèi)存比它大, 會(huì)報(bào)Allowed memory size of .....,
? ? ? ? 2.如果沒有超過設(shè)定的limit,接著ZEND_MM_STORAGE_REALLOC分配segment,當(dāng)!ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size)時(shí),會(huì)報(bào)Out of memory。 分配失敗,報(bào)Out of memory錯(cuò)誤。
這里是malloc失敗,那么是不是服務(wù)器做了什么限制呢,我沒有權(quán)限登錄這臺(tái)服務(wù)器。于是發(fā)信去問,各種問過后發(fā)現(xiàn)是ulimit限制在125M。修改大后錯(cuò)誤消失。
一些參考