PHP5下的Error錯誤處理及問題定位的介紹(程式碼範例)
這篇文章帶給大家的內容是關於PHP5下的Error錯誤處理及問題定位的介紹(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。
來說說當PHP出現E_ERROR等級致命的執行階段錯誤的問題定位方法。例如像Fatal error: Allowed memory size of
記憶體溢出這種。當出現這種錯誤時會導致程式直接退出,PHP的error log中會記錄一條錯誤日誌說明報錯的具體檔案和程式碼行數,其它的任何資訊都沒有了。如果是PHP7的話還可以像捕獲異常一樣捕獲錯誤,PHP5的話就不行了。
一般想到的方法就是看看報錯的具體程式碼,如果報錯檔案是CommonReturn.class.php像下面這個樣子。
<?php /** * 公共返回封装 * Class CommonReturn */ class CommonReturn { /** * 打包函数 * @param $params * @param int $status * * @return mixed */ static public function packData($params, $status = 0) { $res['status'] = $status; $res['data'] = json_encode($params); return $res; } }
其中json_encode那一行報錯了,然後你查了下packData這個方法,有很多項目的類別中都有調用,這時要怎麼定位問題呢?
場景重現
好,首先我們是複現下場景。假如實際呼叫的程式bug.php如下
<?php require_once './CommonReturn.class.php'; $res = ini_set('memory_limit', '1m'); $res = []; $char = str_repeat('x', 999); for ($i = 0; $i < 900 ; $i++) { $res[] = $char; } $get_pack = CommonReturn::packData($res); // something else
運行bug.php PHP錯誤日誌中會記錄
[08-Jan-2019 11:22:52 Asia/Shanghai] PHP Fatal error: Allowed memory size of 1048576 bytes exhausted (tried to allocate 525177 bytes) in /CommonReturn.class.php on line 20
復現成功,錯誤日誌中只是說明了報錯的檔案和哪行程式碼,無法知道程式的上下文堆疊訊息,不知道具體是哪塊業務邏輯呼叫的,這樣一來就無法定位修復錯誤。如果是偶爾出現,也沒有來自前端業務的回饋怎麼檢查呢。
解決想法
1、有人想到了修改memory_limit增加記憶體分配,但這種方法治標不治本。做開發肯定要找到問題的根源。
2、開啟core dump,如果產生code檔案可以進行偵錯,但發現code只有進程異常退出才會產生。像E_ERROR等級的錯誤不一定會產生code文件,記憶體溢出這種可能PHP內部自己就處理了。
3、使用register_shutdown_function註冊一個PHP終止時的回呼函數,再呼叫error_get_last如果獲取到了最後發生的錯誤,就透過debug_print_backtrace取得程式的堆疊訊息,我們試試看。
修改CommonReturn.class.php檔案如下
<?php /** * 公共返回封装 * Class CommonReturn */ class CommonReturn { /** * 打包函数 * @param $params * @param int $status * * @return mixed */ static public function packData($params, $status = 0) { register_shutdown_function(['CommonReturn', 'handleFatal']); $res['status'] = $status; $res['data'] = json_encode($params); return $res; } /** * 错误处理 */ static protected function handleFatal() { $err = error_get_last(); if ($err['type']) { ob_start(); debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5); $trace = ob_get_clean(); $log_cont = 'time=%s' . PHP_EOL . 'error_get_last:%s' . PHP_EOL . 'trace:%s' . PHP_EOL; @file_put_contents('/tmp/debug_' . __FUNCTION__ . '.log', sprintf($log_cont, date('Y-m-d H:i:s'), var_export($err, 1), $trace), FILE_APPEND); } } }
再次執行bug.php,日誌如下。
error_get_last:array ( 'type' => 1, 'message' => 'Allowed memory size of 1048576 bytes exhausted (tried to allocate 525177 bytes)', 'file' => '/CommonReturn.class.php', 'line' => 23, ) trace:#0 CommonReturn::handleFatal()
回溯訊息沒有來源,尷尬了。猜測因為backtrace資訊保存在記憶體中,當出現致命錯誤時會清空。沒辦法,把backtrace從外面傳進來試試。再次修改CommonReturn.class.php。
<?php /** * 公共返回封装 * Class CommonReturn */ class CommonReturn { /** * 打包函数 * @param $params * @param int $status * * @return mixed */ static public function packData($params, $status = 0) { ob_start(); debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5); $trace = ob_get_clean(); register_shutdown_function(['CommonReturn', 'handleFatal'], $trace); $res['status'] = $status; $res['data'] = json_encode($params); return $res; } /** * 错误处理 * @param $trace */ static protected function handleFatal($trace) { $err = error_get_last(); if ($err['type']) { $log_cont = 'time=%s' . PHP_EOL . 'error_get_last:%s' . PHP_EOL . 'trace:%s' . PHP_EOL; @file_put_contents('/tmp/debug_' . __FUNCTION__ . '.log', sprintf($log_cont, date('Y-m-d H:i:s'), var_export($err, 1), $trace), FILE_APPEND); } } }
再次執行bug.php
,日誌如下。
error_get_last:array ( 'type' => 1, 'message' => 'Allowed memory size of 1048576 bytes exhausted (tried to allocate 525177 bytes)', 'file' => '/CommonReturn.class.php', 'line' => 26, ) trace:#0 CommonReturn::packData() called at [/bug.php:13]
成功定位到了呼叫來源,在bug.php的13行。將最終的CommonReturn.class.php發佈到生產環境,再次出現錯誤時候看日誌就可以了。但是這樣的話所有呼叫packData的程式都會執行trace函數,一定也會影響效能的。
總結
對於其中使用到的register_shutdown_function函數需要注意,可以註冊多個不同的回調,但是如果某一個回呼函數中exit了,那麼後面註冊的回呼函數都不會執行。
debug_print_backtrace這個取得回溯資訊函數第一個是否包含請求參數,第二個是回溯記錄層數,我們這裡是不回傳請求參數,可以節省些內存,而且如果請求參數巨大的話調這個函數可能就直接記憶體溢出了。
最好的方法就是升級PHP7,可以像例外一樣捕捉錯誤。
以上是PHP5下的Error錯誤處理及問題定位的介紹(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。
