用gdb調試php程序,gdb調試代碼

本文目錄一覽:

如何 gdb 調試php-fpm

1,安裝strace

[html] view plain copy

sudo apt-get install strace

2,查看php-fpm進程

[html] view plain copy

vagrant@vagrant-ubuntu-precise-64:~$ ps -ef | grep php-fpm

root 2105 1 0 04:02 ? 00:00:02 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)

www-data 2113 2105 0 04:02 ? 00:00:02 php-fpm: pool www

www-data 18481 2105 0 07:05 ? 00:00:01 php-fpm: pool www

www-data 18513 2105 0 07:06 ? 00:00:03 php-fpm: pool www

vagrant 19312 6379 0 10:14 pts/4 00:00:00 grep –color=auto php-fpm

3,調試進程輸出日誌到文件

[html] view plain copy

vagrant@vagrant-ubuntu-precise-64:~$ sudo strace -f -p 2105 -e trace=file -o /temp/trace.log

Process 2105 attached – interrupt to quit

Process 19349 attached

Process 19350 attached

4,查看日誌文件

[html] view plain copy

tail -f /temp/trace.log

如何調試PHP的Core之獲取基本信息

首先, 讓生成一個供舉例子的Core文件: ?phpfunction recurse($num) { recurse(++$num);} recurse(0); 運行這個PHP文件: $ php test.phpSegmentation fault (core dumped) 這個PHP因為無線遞歸, 會導致爆棧, 從而造成 segment fault而在PHP的當前工作目錄產生Coredump文件(如果你的系統沒有產生Coredump文件, 那請查詢ulimit的相關設置). 好, 現在, 讓刪除掉這個test.php, 忘掉上面的代碼, 我們現在僅有的是這個Core文件, 任務是, 找出這個Core產生的原因, 以及發生時候的狀態. 首先, 讓用gdb打開這個core文件: $ gdb php -c core.31656 會看到很多的信息, 首先讓我們注意這段: Core was generated by `php test.php’.Program terminated with signal 11, Segmentation fault. 他告訴我們Core發生的原因:」Segmentation fault」. 一般來說, 這種Core是最常見的, 解引用空指針, double free, 以及爆棧等等, 都會觸發SIGSEGV, 繼而默認的產生Coredump. 現在讓看看Core發生時刻的堆棧: #0 execute (op_array=0xdc9a70) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:5353 memset(EX(CVs), 0, sizeof(zval**) * op_array-last_var);(gdb) bt#0 execute (op_array=0xdc9a70) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:53#1 0x00000000006ea263 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fbf400210) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:234#2 0x00000000006e9f61 in execute (op_array=0xdc9a70) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:92#3 0x00000000006ea263 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fbf400440) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:234#4 0x00000000006e9f61 in execute (op_array=0xdc9a70) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:92#5 0x00000000006ea263 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fbf400670) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:234….. 不停的按回車, 可以看到堆棧很深, 不停的是zend_do_fcall_common_helper_SPEC和execute的重複, 那麼這基本就能斷定是因為產生了無窮大的遞歸(不能一定說是無窮遞歸, 比如之前文章中介紹深悉正則(pcre)最大回溯/遞歸限制). 從而造成爆棧產生的Core. Ok, 那麼現在讓看看, Core發生在PHP的什麼函數中, 在PHP中, 對於FCALL_* Opcode的handler來說, execute_data代表了當前函數調用的一個State, 這個State中包含了信息: (gdb)f 1#1 0x00000000006ea263 in zend_do_fcall_common_helper_SPEC (execute_data=0x7fbf400210) at /home/laruence/package/php-5.2.14/Zend/zend_vm_execute.h:234234 zend_execute(EG(active_op_array) TSRMLS_CC);(gdb) p execute_data-function_state.function-common-function_name$3 = 0x2a95b65a78 “recurse”(gdb) p execute_data-function_state.function-op_array-filename$4 = 0x2a95b632a0 “/home/laruence/test.php”(gdb) p execute_data-function_state.function-op_array-line_start$5 = 2 現在我們得到, 在調用的PHP函數是recurse, 這個函數定義在/home/laruence/test.php的第二行 經過重複驗證幾個frame, 可以看出, 一直是在重複調用這個PHP函數. 要注意的是, 為了介紹查看執行信息的原理, 我才採用原生的gdb的print來查看, 其實我們還可以使用PHP源代碼中提供的.gdbinit(gdb命令編寫腳本), 來簡單的獲取到上面的信息: (gdb) source /home/laruence/package/php-5.2.14/.gdbinit(gdb) zbacktrace[0xbf400210] recurse() /home/laruence/test.php:3[0xbf400440] recurse() /home/laruence/test.php:3[0xbf400670] recurse() /home/laruence/test.php:3[0xbf4008a0] recurse() /home/laruence/test.php:3[0xbf400ad0] recurse() /home/laruence/test.php:3[0xbf400d00] recurse() /home/laruence/test.php:3[0xbf400f30] recurse() /home/laruence/test.php:3[0xbf401160] recurse() /home/laruence/test.php:3….. 關於.gdbinit, 是一段小小的腳本文件, 定義了一些方便我們去調試PHP的Core, 大家也可以用文本編輯器打開, 看看裡面定義的一些快捷的命令, 一般來說, 我常用的有: zbacktraceprint_ht**系列zmemcheck OK, 回歸正題, 我們現在知道, 問題發生在/home/laruence/test.php的recurse函數的遞歸調用上了. 現在, 讓我們來看看, 在調用這個函數的時候的參數是什麼? PHP的參數傳遞是依靠一個全局Stack來完成的, 也就是EG(argument_stack), EG在非多線程情況下就是executor_globals, 它保持了很多執行狀態. 而argument_statck就是參數的傳遞棧, 保存著對應PHP函數調用層數相當的調用參數. 要注意的是, 這個PHP函數調用堆棧(層數)不和gdb所看到的backtrace簡單的一一對應, 所以參數也不能直接和gdb的backtrace對應起來, 需要單獨分析: //先看看, 最後一次函數調用的參數數目是多少(gdb) p (int )*(executor_globals-argument_stack-top_element – 2)$13 = 1 //再看看, 最後一次函數調用的參數是什麼(gdb) p **(zval **)(executor_globals-argument_stack-top_element – 3)$2 = {value = {lval = 22445, dval = 1.1089303420906779e-319, str = {val = 0x57ad Address 0x57ad out of bounds, len = 7}, ht = 0x57ad, obj = {handle = 22445, handlers = 0x7}}, refcount = 2, type = 1 ‘\001’, is_ref = 0 ‘\0’} 好, 我們現在得到, 最後一次調用的參數是一個整數, 數值是22445 到了這一步, 我們就得到了這個Core發生的時刻的PHP層面的相關信息, 接下來, 就可以交給對應的PHP開發工程師來排查, 這個參數下, 可能造成的無窮大遞歸的原因, 從而修復這個問題..

如何使用GDB調試PHP程序

如果想html寫出來,那這個回帖必須支持html,如果不支持,發出來的就是代碼源碼了。

如果是dz性質的論壇且支持html語言,點高級模式,然後點純文本,將html源碼貼上來,提交即可。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/186981.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-27 13:34
下一篇 2024-11-27 13:34

相關推薦

  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • python強行終止程序快捷鍵

    本文將從多個方面對python強行終止程序快捷鍵進行詳細闡述,並提供相應代碼示例。 一、Ctrl+C快捷鍵 Ctrl+C快捷鍵是在終端中經常用來強行終止運行的程序。當你在終端中運行…

    編程 2025-04-29
  • PHP和Python哪個好找工作?

    PHP和Python都是非常流行的編程語言,它們被廣泛應用於不同領域的開發中。但是,在考慮擇業方向的時候,很多人都會有一個問題:PHP和Python哪個好找工作?這篇文章將從多個方…

    編程 2025-04-29
  • Python字元串寬度不限制怎麼打代碼

    本文將為大家詳細介紹Python字元串寬度不限制時如何打代碼的幾個方面。 一、保持代碼風格的統一 在Python字元串寬度不限制的情況下,我們可以寫出很長很長的一行代碼。但是,為了…

    編程 2025-04-29
  • Python程序需要編譯才能執行

    Python 被廣泛應用於數據分析、人工智慧、科學計算等領域,它的靈活性和簡單易學的性質使得越來越多的人喜歡使用 Python 進行編程。然而,在 Python 中程序執行的方式不…

    編程 2025-04-29
  • Python基礎代碼用法介紹

    本文將從多個方面對Python基礎代碼進行解析和詳細闡述,力求讓讀者深刻理解Python基礎代碼。通過本文的學習,相信大家對Python的學習和應用會更加輕鬆和高效。 一、變數和數…

    編程 2025-04-29
  • Python程序文件的拓展

    Python是一門功能豐富、易於學習、可讀性高的編程語言。Python程序文件通常以.py為文件拓展名,被廣泛應用於各種領域,包括Web開發、機器學習、科學計算等。為了更好地發揮P…

    編程 2025-04-29
  • 倉庫管理系統代碼設計Python

    這篇文章將詳細探討如何設計一個基於Python的倉庫管理系統。 一、基本需求 在著手設計之前,我們首先需要確定倉庫管理系統的基本需求。 我們可以將需求分為以下幾個方面: 1、庫存管…

    編程 2025-04-29
  • Python滿天星代碼:讓編程變得更加簡單

    本文將從多個方面詳細闡述Python滿天星代碼,為大家介紹它的優點以及如何在編程中使用。無論是剛剛接觸編程還是資深程序員,都能從中獲得一定的收穫。 一、簡介 Python滿天星代碼…

    編程 2025-04-29
  • 寫代碼新手教程

    本文將從語言選擇、學習方法、編碼規範以及常見問題解答等多個方面,為編程新手提供實用、簡明的教程。 一、語言選擇 作為編程新手,選擇一門編程語言是很關鍵的一步。以下是幾個有代表性的編…

    編程 2025-04-29

發表回復

登錄後才能評論