GDB を使用して PHP コードをデバッグし、PHP コードの無限ループの問題を解決する (gdbphp_PHP チュートリアル)

WBOY
リリース: 2016-07-13 10:05:38
オリジナル
940 人が閲覧しました

GDB を使用して PHP コードをデバッグし、PHP コードの無限ループ問題を解決します。 gdbphp

最近、同僚が Swoole Server の問題を解決するのを手伝っていたとき、1 つのワーカー プロセスが常に R 状態であることに気付きました。 CPU 消費量が非常に高かった。暫定的な結論は、PHP コードで無限ループが発生するということです。

次のコードは、PHP の無限ループ問題を解決する方法を示しています。

コードをコピーします コードは次のとおりです:
#デッドループ.php
$array = array();
for($i = 0; $i {
$array[] = $i;
}
include __DIR__."/include.php";
#include.php
その間(1)
{
usleep(10);
$keys = array_flip($array);
$index = array_search(rand(1500, 9999), $array);
$str = str_repeat('A', $index);
$strb = テスト($index, $str);
}
関数テスト($index, $str)
{
str_replace('A', 'B', $str);
を返します }

次のように ps aux を通じてプロセス ID とステータスを取得し、gdb -p process ptrace tracking を使用して、bt コマンドを通じてコールスタックを取得します

コードをコピーします コードは次のとおりです:
htf 3834 2.6 0.2 166676 22060 ポイント/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)
/home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:1485
で #1 0x00000000008cd643 _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) /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) /home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:2436
#3 _zval_ptr_dtor の 0x00000000008eda0a (zval_ptr=0x25849a0, __zend_filename=0xee3d40 "/home/htf/workspace/php-5.4.27/Zend/zend_variables.c", __zend_lineno=182)
/home/htf/workspace/php-5.4.27/Zend/zend_execute_API.c:437
で /home/htf/workspace/php-5.4.27/Zend/zend_variables.c:182 の _zval_ptr_dtor_wrapper (zval_ptr=0x25849a0) の #4 0x00000000008fe687
#5 0x000000000091259f zend_hash_destroy (ht=0x7f7263f6e380) (/home/htf/workspace/php-5.4.27/Zend/zend_hash.c:560)
#6 _zval_dtor_func の 0x00000000008fe2c5 (zvalue=0x7f726426fe50, __zend_filename=0xeea290 "/home/htf/workspace/php-5.4.27/Zend/zend_execute.c", __zend_lineno=901)
/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)
/home/htf/workspace/php-5.4.27/Zend/zend_variables.h:35
にあります #8 0x0000000000939747 zend_assign_to_variable (variable_ptr_ptr=0x7f7263f8e738, value=0x7f726426f6a8) at /home/htf/workspace/php-5.4.27/Zend/zend_execute.c:901
/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:33168 の ZEND_ASSIGN_SPEC_CV_VAR_HANDLER (execute_data=0x7f726d04b2a8) の #9 0x0000000000997ee5
#10 0x000000000093b5fd の実行 (op_array=0x21d58b0) (/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:410)
#11 0x0000000000901692 zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/htf/workspace/php-5.4.27/Zend/zend.c:1315
#12 0x000000000087926a php_execute_script (primary_file=0x7ffffe0038d0) (/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 メイン (argc=2, argv=0x7ffffe004d18) の 0x00000000009a4491 /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) /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) /home/htf/workspace/php-5.4.27/Zend/zend_alloc.c:2425
#2 0x0000000000911d85 _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) /home/htf/workspace/php-5.4.27/Zend/zend_hash.c: 412
#3 zif_array_flip の 0x00000000007767e1 (ht=1、return_value=0x7f726424ea68、return_value_ptr=0x0、this_ptr=0x0、return_value_used=1)
/home/htf/workspace/php-5.4.27/ext/standard/array.c:2719
にあります #4 zend_do_fcall_common_helper_SPEC (execute_data=0x7f726d04b2a8) の 0x000000000093c03e (/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:643)
/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:2233 の ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x7f726d04b2a8) の #5 0x00000000009400e6
#6 0x000000000093b5fd の実行 (op_array=0x21d58b0) (/home/htf/workspace/php-5.4.27/Zend/zend_vm_execute.h:410)

2 回の BT 情報とは異なり、これはプログラムが別の場所で中断されたためです。この行を実行 (oparray=0x21d58b0) します。これは、PHP が oparray を実行するためのエントリです。gdb の下に 6 を入力します。入手可能です)。

复制代码代码如下: (gdb) f 6
#6 0x000000000093b5fd の実行 (op_array=0x21d58b0) (/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 ' 02'、function_name = 0x7f726d086540 "テスト"、スコープ = 0x0、fn_flags = 134217728、プロトタイプ = 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、リテラル = 0x7f726424eae0、last_literal = 4、run_time_cache = 0x7f726450bfb0、last_cache_slot = 1、予約済み = {0x0, 0x0, 0x0, 0x0}}

ここのファイル名から、op_array が 1 つの PHP ファイルであることがわかります。その後、f 0 を現在の位置に入力します。

复制代码代码如下: (gdb) p **executor_globals.opline_ptr $4 = {ハンドラー = 0x93ff9c 、op1 = {定数 = 1680133296、変数 = 1680133296、数値 = 1680133296、ハッシュ = 140129283132592、opline_num = 1680133296、
jmp_addr = 0x7f726424ccb0、zv = 0x7f726424ccb0、リテラル = 0x7f726424ccb0、ptr = 0x7f726424ccb0}、op2 = {定数 = 0、var = 0、num = 0、ハッシュ = 0、opline_num = 0、jmp_addr = 0 ×0、
zv = 0x0、リテラル = 0x0、ptr = 0x0}、結果 = {constant = 32、var = 32、num = 32、hash = 32、opline_num = 32、jmp_addr = 0x20、zv = 0x20、リテラル = 0x20、ptr = 0x20}、
拡張値 = 1、行番号 = 5、オペコード = 60 '

ここの lineno は、OPCODE にあるコード行数を示します。GDB を使用すると、ここでさらに多くの情報を参照できます。 。

zbacktraceの使用

zend 官は、命令がカプセル化され、php 関数の調整関係を直接参照できる gdb のスクリプトを提供しています。php ソース コードのルート ディレクトリに 1 つの .gdbinit があります。

复制代码

代码如下: ソース your_php_src_path/.gdbinit zバックトレース
PHP 関数の調整用スタックを直接参照できます。
以上が本書のすべての内容です、皆様がご満足いただけることを願っております。

http://www.bkjia.com/PHPjc/963122.html

www.bkjia.com

tru​​e

http://www.bkjia.com/PHPjc/963122.html技術記事 GDB 试 PHP 代コード、解决 PHP 代解死循環问题、gdbphp を使用して最近同じ問題を解決した Swoole Server のときに、1 人のワーカーが常に R の状態にあり、CPU 消費時間が...
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!