Inhaltsverzeichnis
使用GDB调试PHP代码,解决PHP代码死循环问题,gdbphp
Heim Backend-Entwicklung PHP-Tutorial 使用GDB调试PHP代码,解决PHP代码死循环问题,gdbphp_PHP教程

使用GDB调试PHP代码,解决PHP代码死循环问题,gdbphp_PHP教程

Jul 13, 2016 am 10:05 AM
gdb 死循环 PHP-Code debuggen

使用GDB调试PHP代码,解决PHP代码死循环问题,gdbphp

最近在帮同事解决Swoole Server问题时,发现有1个worker进程一直处于R的状态,而且CPU耗时非常高。初步断定是PHP代码中发生死循环。

下面通过一段代码展示如何解决PHP死循环问题。

复制代码 代码如下:
#dead_loop.php
$array = array();
for($i = 0; $i {
    $array[] = $i;
}
include __DIR__."/include.php";
#include.php
while(1)
{
    usleep(10);
    $keys = array_flip($array);
    $index = array_search(rand(1500, 9999), $array);
    $str = str_repeat('A', $index);
    $strb = test($index, $str);
}
function test($index, $str)
{
    return str_replace('A', 'B', $str);
}

通过ps aux得到进程ID和状态如下,使用gdb -p 进程ptrace跟踪,通过bt命令得到调用栈

复制代码 代码如下:
htf 3834 2.6 0.2 166676 22060 pts/12 R+ 10:50 0:12 php dead_loop.php
gdb -p 3834
(gdb) bt
#0 0x00000000008cc03f in zend_mm_check_ptr (heap=0x1eaa2c0, ptr=0x2584910, silent=1, __zend_filename=0xee3d40 "/home/htf/workspace/php-5.4.27/Zend/zend_variables.c",
__zend_lineno=182, __zend_orig_filename=0xee1888 "/home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c", __zend_orig_lineno=437)
at /home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:1485
#1 0x00000000008cd643 in _zend_mm_free_int (heap=0x1eaa2c0, p=0x2584910, __zend_filename=0xee3d40 "/home/htf/workspace/php-5.4.27/Zend/zend_variables.c", __zend_lineno=182,
__zend_orig_filename=0xee1888 "/home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c", __zend_orig_lineno=437) at /home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:2064
#2 0x00000000008cebf7 in _efree (ptr=0x2584910, __zend_filename=0xee3d40 "/home/htf/workspace/php-5.4.27/Zend/zend_variables.c", __zend_lineno=182,
__zend_orig_filename=0xee1888 "/home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c", __zend_orig_lineno=437) at /home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:2436
#3 0x00000000008eda0a in _zval_ptr_dtor (zval_ptr=0x25849a0, __zend_filename=0xee3d40 "/home/htf/workspace/php-5.4.27/Zend/zend_variables.c", __zend_lineno=182)
at /home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c:437
#4 0x00000000008fe687 in _zval_ptr_dtor_wrapper (zval_ptr=0x25849a0) at /home/htf/workspace/php-5.4.27/Zend/zend_variables.c:182
#5 0x000000000091259f in zend_hash_destroy (ht=0x7f7263f6e380) at /home/htf/workspace/php-5.4.27/Zend/zend_hash.c:560
#6 0x00000000008fe2c5 in _zval_dtor_func (zvalue=0x7f726426fe50, __zend_filename=0xeea290 "/home/htf/workspace/php-5.4.27/Zend/zend_execute.c", __zend_lineno=901)
at /home/htf/workspace/php-5.4.27/Zend/zend_variables.c:45
#7 0x0000000000936656 in _zval_dtor (zvalue=0x7f726426fe50, __zend_filename=0xeea290 "/home/htf/workspace/php-5.4.27/Zend/zend_execute.c", __zend_lineno=901)
at /home/htf/workspace/php-5.4.27/Zend/zend_variables.h:35
#8 0x0000000000939747 in zend_assign_to_variable (variable_ptr_ptr=0x7f7263f8e738, value=0x7f726426f6a8) at /home/htf/workspace/php-5.4.27/Zend/zend_execute.c:901
#9 0x0000000000997ee5 in ZEND_ASSIGN_SPEC_CV_VAR_HANDLER (execute_data=0x7f726d04b2a8) at /home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:33168
#10 0x000000000093b5fd in execute (op_array=0x21d58b0) at /home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:410
#11 0x0000000000901692 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/htf/workspace/php-5.4.27/Zend/zend.c:1315
#12 0x000000000087926a in php_execute_script (primary_file=0x7ffffe0038d0) at /home/htf/workspace/php-5.4.27/main/main.c:2502
#13 0x00000000009a32e3 in do_cli (argc=2, argv=0x7ffffe004d18) at /home/htf/workspace/php-5.4.27/sapi/cli/php_cli.c:989
#14 0x00000000009a4491 in main (argc=2, argv=0x7ffffe004d18) at /home/htf/workspace/php-5.4.27/sapi/cli/php_cli.c:1365

执行gdb后,死循环的进程会变成T的状态,表示正在Trace。这个是独占的,所以不能再使用strace/gdb或者其他ptrace工具对此进程进行调试。另外此进程会中断执行。gdb输入c后,程序继续向下运行。然后再次按下ctrl + c中断程序。 通过bt命令查看进程的调用栈。

复制代码 代码如下:
(gdb) bt
#0 _zend_mm_alloc_int (heap=0x1eaa2c0, size=72, __zend_filename=0xe43410 "/home/htf/workspace/php-5.4.27/ext/standard/array.c", __zend_lineno=2719,
__zend_orig_filename=0xee5a38 "/home/htf/workspace/php-5.4.27/Zend/zend_hash.c", __zend_orig_lineno=412) at /home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:1895
#1 0x00000000008ceb86 in _emalloc (size=72, __zend_filename=0xe43410 "/home/htf/workspace/php-5.4.27/ext/standard/array.c", __zend_lineno=2719,
__zend_orig_filename=0xee5a38 "/home/htf/workspace/php-5.4.27/Zend/zend_hash.c", __zend_orig_lineno=412) at /home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:2425
#2 0x0000000000911d85 in _zend_hash_index_update_or_next_insert (ht=0x2257a10, h=3972, pData=0x7ffffe0012b0, nDataSize=8, pDest=0x0, flag=1,
__zend_filename=0xe43410 "/home/htf/workspace/php-5.4.27/ext/standard/array.c", __zend_lineno=2719) at /home/htf/workspace/php-5.4.27/Zend/zend_hash.c:412
#3 0x00000000007767e1 in zif_array_flip (ht=1, return_value=0x7f726424ea68, return_value_ptr=0x0, this_ptr=0x0, return_value_used=1)
at /home/htf/workspace/php-5.4.27/ext/standard/array.c:2719
#4 0x000000000093c03e in zend_do_fcall_common_helper_SPEC (execute_data=0x7f726d04b2a8) at /home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:643
#5 0x00000000009400e6 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x7f726d04b2a8) at /home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:2233
#6 0x000000000093b5fd in execute (op_array=0x21d58b0) at /home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:410

两次的BT信息不一样,这是因为程序在不同的位置中断。看到execute (oparray=0x21d58b0) 这一行,这里就是PHP执行oparray的入口了。gdb下输入f 6,(通过调用栈编号可得)。

复制代码 代码如下:
(gdb) f 6
#6 0x000000000093b5fd in execute (op_array=0x21d58b0) at /home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:410
410 if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > 0) {
(gdb) p *op_array
$2 = {type = 2 '\002', function_name = 0x7f726d086540 "test", scope = 0x0, fn_flags = 134217728, prototype = 0x0, num_args = 2, required_num_args = 2, arg_info = 0x7f726d086bd8,
refcount = 0x7f726d0870f0, opcodes = 0x7f726424d600, last = 8, vars = 0x7f726424e890, last_var = 2, T = 1, brk_cont_array = 0x0, last_brk_cont = 0, try_catch_array = 0x0,
last_try_catch = 0, static_variables = 0x0, this_var = 4294967295, filename = 0x7f726424ba38 "/home/htf/wwwroot/include.php", line_start = 12, line_end = 15, doc_comment = 0x0,
doc_comment_len = 0, early_binding = 4294967295, literals = 0x7f726424eae0, last_literal = 4, run_time_cache = 0x7f726450bfb0, last_cache_slot = 1, reserved = {0x0, 0x0, 0x0, 0x0}}

这里的filename就能看到op_array是哪个PHP文件的。然后输入f 0进入当前位置。

复制代码 代码如下:
(gdb) p **executor_globals.opline_ptr
$4 = {handler = 0x93ff9c , op1 = {constant = 1680133296, var = 1680133296, num = 1680133296, hash = 140129283132592, opline_num = 1680133296,
jmp_addr = 0x7f726424ccb0, zv = 0x7f726424ccb0, literal = 0x7f726424ccb0, ptr = 0x7f726424ccb0}, op2 = {constant = 0, var = 0, num = 0, hash = 0, opline_num = 0, jmp_addr = 0x0,
zv = 0x0, literal = 0x0, ptr = 0x0}, result = {constant = 32, var = 32, num = 32, hash = 32, opline_num = 32, jmp_addr = 0x20, zv = 0x20, literal = 0x20, ptr = 0x20},
extended_value = 1, lineno = 5, opcode = 60 '

这里的lineno表示OPCODE所在的代码行数,可以到对应文件里去看下是哪行代码。使用GDB可以查看到更多的信息,这里就不再一一介绍了,有兴趣各位可以自行尝试。

zbacktrace的使用

zend官方提供了一个gdb的脚本,对指令进行了封装,可以直接看到php函数的调用关系。在php源代码包的根目录中有一个.gdbinit。使用

复制代码 代码如下:
source your_php_src_path/.gdbinit
zbacktrace

可以直接看到PHP函数的调用堆栈。

以上就是本文的全部内容了,希望大家能够喜欢。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/963122.htmlTechArticle使用GDB调试PHP代码,解决PHP代码死循环问题,gdbphp 最近在帮同事解决Swoole Server问题时,发现有1个worker进程一直处于R的状态,而且CPU耗时非...
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Gängige Konfigurationstechniken zum Debuggen des Linux-Kernels mithilfe von GDB Gängige Konfigurationstechniken zum Debuggen des Linux-Kernels mithilfe von GDB Jul 05, 2023 pm 01:54 PM

Gängige Konfigurationstechniken für die Verwendung von GDB zum Debuggen des Linux-Kernels. Einführung: In der Linux-Entwicklung ist die Verwendung von GDB zum Debuggen des Kernels eine sehr wichtige Fähigkeit. GDB ist ein leistungsstarkes Debugging-Tool, das Entwicklern dabei helfen kann, Fehler im Kernel schnell zu finden und zu beheben. In diesem Artikel werden einige gängige GDB-Konfigurationstechniken vorgestellt und erläutert, wie GDB zum Debuggen des Linux-Kernels verwendet wird. 1. Konfigurieren Sie die GDB-Umgebung. Zuerst müssen wir die GDB-Umgebung auf dem Linux-System konfigurieren. Bitte stellen Sie sicher, dass auf Ihrem System das GDB-Tool installiert ist

Gängige Konfigurationsmethoden für die Verwendung von GDB zum Debuggen eingebetteter ARM-Programme unter Linux Gängige Konfigurationsmethoden für die Verwendung von GDB zum Debuggen eingebetteter ARM-Programme unter Linux Jul 05, 2023 am 08:10 AM

Gängige Konfigurationsmethoden für die Verwendung von GDB zum Debuggen eingebetteter ARM-Programme unter Linux. Als spezielles Computersystem werden eingebettete Systeme normalerweise in elektronische Geräte integriert und zur Steuerung und Verwaltung von Hardwareressourcen verwendet. Um den Betrieb eingebetteter Systeme zu debuggen und zu analysieren, müssen wir spezielle Tools verwenden. Unter diesen ist GDB ein häufig verwendeter Open-Source-Debugger, der auf eingebetteten Systemen ausgeführt werden und mit Programmen kommunizieren kann. In diesem Artikel werden gängige Konfigurationsmethoden für die Verwendung von GDB zum Debuggen eingebetteter ARM-Programme unter Linux vorgestellt und Codebeispiele gegeben.

Wie debugge ich Golang-Funktionen mit GDB? Wie debugge ich Golang-Funktionen mit GDB? Apr 18, 2024 am 08:00 AM

Die Schritte zur Verwendung von GDB zum Debuggen von Go-Funktionen lauten wie folgt: Installieren Sie das GDB- und Go-Debugging-Paket. Kompilieren Sie das Programm mit aktivierten Debug-Informationen. Verwenden Sie GDB, um das Programm zu starten. Haltepunkte setzen. Verwenden Sie den Befehl „run“, um das Programm zu starten. Verwenden Sie zum Debuggen Debug-Befehle.

So lösen Sie das Endlosschleifenproblem in der C++-Entwicklung So lösen Sie das Endlosschleifenproblem in der C++-Entwicklung Aug 22, 2023 am 08:53 AM

So lösen Sie das Endlosschleifenproblem in der C++-Entwicklung. In der C++-Entwicklung ist die Endlosschleife ein sehr häufiges, aber sehr schwieriges Problem. Wenn ein Programm in eine Endlosschleife gerät, führt dies dazu, dass das Programm nicht normal ausgeführt werden kann und möglicherweise sogar zum Systemabsturz führt. Daher ist das Lösen von Endlosschleifenproblemen eine der wesentlichen Fähigkeiten in der C++-Entwicklung. In diesem Artikel werden einige gängige Methoden zur Lösung des Endlosschleifenproblems vorgestellt. Überprüfen der Schleifenbedingungen Eine der häufigsten Ursachen für Endlosschleifen sind falsche Schleifenbedingungen. Wenn die Schleifenbedingung immer wahr ist, wird die Schleife weiter ausgeführt, was zu einer Endlosschleife führt.

Gängige Konfigurationsmethoden für die Verwendung von GDB zum Debuggen von Multithread-Programmen unter Linux Gängige Konfigurationsmethoden für die Verwendung von GDB zum Debuggen von Multithread-Programmen unter Linux Jul 04, 2023 pm 02:49 PM

Gängige Konfigurationsmethoden für die Verwendung von GDB zum Debuggen von Multithread-Programmen unter Linux Einführung: Bei der Multithread-Programmierung ist das Debuggen eine wesentliche Aufgabe. GDB ist ein leistungsstarker Debugger, der uns beim Auffinden und Beheben von Fehlern in Multithread-Programmen helfen kann. In diesem Artikel werden gängige Konfigurationsmethoden für die Verwendung von GDB zum Debuggen von Multithread-Programmen unter Linux vorgestellt und Codebeispiele bereitgestellt, um den Lesern dabei zu helfen, GDB besser zu verstehen und zu verwenden. 1. GDB installieren Zuerst müssen wir GDB im Linux-System installieren. Geben Sie das Terminal ein

Gängige Debugging-Tools und -Techniken für Linux-Systeme Gängige Debugging-Tools und -Techniken für Linux-Systeme Feb 23, 2024 pm 02:40 PM

In Linux-Systemen ist das Debuggen ein entscheidender Teil des Programmentwicklungs- und Wartungsprozesses. Um Entwickler beim effektiveren Debuggen zu unterstützen, bietet Linux eine Vielzahl leistungsstarker Debugging-Tools und -Technologien. In diesem Artikel werden einige häufig verwendete Linux-Debugging-Tools und -Techniken kurz vorgestellt, um Entwicklern beim Debuggen zu helfen. 1. Debugging-Tools 1.gdb In Linux-Systemen wird gdb häufig als eines der Debugging-Tools verwendet. Es hilft Entwicklern, die Ursache von Programmabstürzen zu ermitteln und bietet eine Reihe von Befehlen zum Überprüfen des Programmstatus, zum Ändern von Variablen und zum Ausführen von Code . Um mit dem Debuggen zu beginnen, können Sie den folgenden Befehl verwenden. $gdb./program, wobei „./program“ die ausführbare Datei darstellt, die debuggt werden soll. Sobald GDB startet,

So beheben Sie die Endlosschleife in Win10 automatisch So beheben Sie die Endlosschleife in Win10 automatisch Dec 27, 2023 pm 04:04 PM

Die automatische Reparaturschleife von Win10 ist für viele Benutzer ein häufiges Problem und hat den meisten Benutzern große Probleme bereitet. Gibt es also eine Schaltfläche, mit der er direkt beenden kann? Werfen wir einen Blick auf das ausführliche Tutorial unten. Win10 repariert die Endlosschleife automatisch. Dies hängt hauptsächlich von der Marke des Computers ab. Die am häufigsten verwendeten Tasten sind F9 und F11 Wenn der Computer eingeschaltet ist, drücken Sie F2, um den Lenovo-Computer aufzurufen. Wählen Sie zu diesem Zeitpunkt Lenovo One-Key Recovery aus oder drücken Sie direkt die Taste „R“ auf der Tastatur. Drücken Sie die linke und rechte Taste, um „Weiter“ auszuwählen. Nun gelangen Sie zu „Lenovo One-key Recovery“. Bei der Eingabe gibt es drei Optionen, nämlich Systemwiederherstellung, Systemsicherung und Backup-Deinstallation

So lösen Sie: Java-Algorithmusfehler: Endlosschleife So lösen Sie: Java-Algorithmusfehler: Endlosschleife Aug 25, 2023 pm 10:12 PM

So lösen Sie: Java-Algorithmusfehler: Endlosschleife Einführung: Beim Schreiben von Java-Programmen stoßen wir häufig auf verschiedene Fehler und Ausnahmen. Unter diesen ist die Endlosschleife ein häufiges Problem, das dazu führt, dass das Programm in einen Endlosschleifenzustand fällt und die normale Ausführung des Programms fehlschlägt. In diesem Artikel diskutieren wir, wie das Endlosschleifenproblem in Java-Algorithmen gelöst werden kann, und stellen Beispielcode bereit. 1. Definition und Ursache einer Endlosschleife: Eine Endlosschleife bezieht sich auf eine Schleifenstruktur in einem Programm, die keine Bedingungen für eine normale Beendigung hat und dazu führt, dass das Programm in einer Endlosschleife innerhalb dieser Schleife ausgeführt wird.

See all articles