热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于php:PHPDebug互动扩展phpdbg功能浅析

对于PHP开发者来说,单步的断点Debug调试并不是咱们的必修课,而Java、C#、C++这些动态语言则会经常性地进行这种调试。其实,咱们PHP也是反对这类调试形式的,特地是对于理解一些开源框架,或者有十分深层次的Bug跟踪时,断点调试会十分有用。

对于 PHP 开发者来说,单步的断点 Debug 调试并不是咱们的必修课,而 Java 、 C# 、 C++ 这些动态语言则会经常性地进行这种调试。其实,咱们 PHP 也是反对这类调试形式的,特地是对于理解一些开源框架,或者有十分深层次的 Bug 跟踪时,断点调试会十分有用。

不少接触过 PHP 断点调试的肯定都用过鼎鼎大名的 XDebug 。不过咱们明天讲的并不是这款扩大,而是另一个曾经集成到 PHP 官网源码中的调试工具,并且,最重要的是,它调试时看到的内容是更为底层的 opcode 执行过程。话不多说,咱们间接进入到 phpdbg 这款工具的学习中吧!!

phpdbg 命令行性能

在咱们装置好 PHP 后,默认就有了 phpdbg 这个工具。间接在命令行运行就会进入这个工具。

% phpdbg
[Welcome to phpdbg, the interactive PHP debugger, v0.5.0]
To get help using phpdbg type "help" and press enter
[Please report bugs to ]

没错,它就是随 PHP 装置的时候默认自带的,如果你的环境变量中没有这个工具命令的话,能够在 PHP 装置目录的 bin/ 目录上面找到。

在进入 phpdbg 环境后,咱们应用 help 就能够查看它的操作阐明。

prompt> help

phpdbg is a lightweight, powerful and easy to use debugging platform for PHP5.4+
It supports the following commands:

Information
  list      list PHP source
  info      displays information on the debug session
  print     show opcodes
  frame     select a stack frame and print a stack frame summary
  generator show active generators or select a generator frame
  back      shows the current backtrace
  help      provide help on a topic
……

帮忙文档十分长,大家能够本人查看具体的内容,其中有一个 help 命令能够让咱们看到许多简写的命令,咱们次要应用这些简写的命令别名就能够。

prompt> help aliases
Below are the aliased, short versions of all supported commands
 e     exec                  set execution context
 s     step                  step through execution
 c     continue              continue execution
 r     run                   attempt execution
 u     until                 continue past the current l

命令的简介和查看都很简略,那么咱们要如何来调试 PHP 文件呢?这个才是咱们最关怀的事件。在调试一个文件的时候,咱们须要将它载入到以后的执行环境中。能够在以后 phpdbg 环境中应用 e 命令指定文件进行载入,也能够在运行 phpdbg 的时候通过 -e 来指定须要载入的文件。

% phpdbg -e PHPDebug互动扩大.php
[Welcome to phpdbg, the interactive PHP debugger, v0.5.0]
To get help using phpdbg type "help" and press enter
[Please report bugs to ]
[Successful compilation of /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
prompt> 

这里咱们应用的是第二种形式,在启动 phpdbg 时应用 -e 参数来指定须要载入的文件。

一般断点设置

载入了文件,进入了命令行,咱们就能够进行断点调试了。首先,咱们应用代码形式来设置断点。在下面的测试文件中,咱们应用上面的形式来定义断点。

echo 111;
phpdbg_break_file("PHPDebug互动扩大.php", 3);

echo 222;
phpdbg_break_file("PHPDebug互动扩大.php", 6);

phpdbg_break_file() 函数就是来定义断点的,它有两个参数,第一个参数是文件名,这个不能乱填。第二个参数是断点的行号。

接下来,在命令行中,咱们运行两次简写的 run 命令 r 。

prompt> r
111
[Breakpoint #0 added at /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:3]
222
[Breakpoint #1 added at /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:6]
[Script ended normally]

prompt> r
[Breakpoint #0 at /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:3, hits: 1]
>00003: echo 111;
 00004: phpdbg_break_file("PHPDebug互动扩大.php", 3);
 00005: 
prompt> 

能够看出,在第一次运行 r 的时候, phpdbg 将整个文件进行了一次扫描并输入了以后的两个断点信息。而后再运行一次 r 则定位到了第3行,也就是第一个断点的地位。接下来,咱们就要进行单步调试了,咱们间接应用 step 的简写命令 s 。

prompt> s
[L3          0x10ecae220 ECHO                    111                                                            /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
111
[L4          0x10ecae240 EXT_STMT                                                                               /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
>00004: phpdbg_break_file("PHPDebug互动扩大.php", 3);
 00005: 
 00006: echo 222;
prompt> 

断点地位向下运行了,果然是合乎咱们的预期,开始了一行一行的单步运行。在下面输入的内容中,咱们看到了 opcode 运行的状态。比方 L3 0x10ecae220 ECHO 这一行指的就是第 3 行执行了 ECHO 操作。是不是感觉十分高大上。

一路 s 下来,走到最初咱们就完结了这次断点调试,phpdbg 环境将退出 run 运行时。

……
prompt> s
[Script ended normally]
prompt> s
[Not running]
prompt> 

这样,一趟调试就实现了。当咱们在第一个断点不想单步调试,想间接进入下一个断点,就能够应用 continue 的简写命令 c 来间接跳到下一个断点。

prompt> r
Do you really want to restart execution? (type y or n): y
[Breakpoint #0 at /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:3, hits: 1]
>00003: echo 111;
 00004: phpdbg_break_file("PHPDebug互动扩大.php", 3);
 00005: 

prompt> c
111
[Breakpoint at /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:3 exists]
[Breakpoint #1 at /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:6, hits: 1]
>00006: echo 222;
 00007: phpdbg_break_file("PHPDebug互动扩大.php", 6);
 00008: 
prompt> 

另外还有一个命令就是能够间接看到以后载入的文件环境中的所有断点信息的。

prompt> info break
------------------------------------------------
File Breakpoints:
#0              /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:3
#1              /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:6

以上,就是一个简略的行断点设置以及调试步骤。当然,咱们只是针对一个简略文件的测试,对于简单的框架型零碎,断点的设置和调试就会简单很多,不过相应地,咱们可能看到底层的 opcode 代码的执行状况,也能让咱们对所测试的内容有更加深刻的理解。

办法断点及运行步骤剖析

接下来咱们来设置一个办法断点,并一步步察看 opcode 的状况。

$i = 1;
// phpdbg -e PHP\ Debug互动扩大.php
function testFunc(){
    global $i;
    $i += 3;
    echo "This is testFunc! i:" . $i, PHP_EOL;
}

testFunc();
phpdbg_break_function('testFunc');

在 PHP 代码中,咱们应用 phpdbg_break_function() 来给这个 testFunc() 办法设置一个断点。当代码中调用这个函数的时候,就会进入这个断点中。

prompt> r
[Breakpoint #0 in testFunc() at /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:11, hits: 1]
>00011: function testFunc(){
 00012:     global $i;
 00013:     $i += 3;

prompt> s
[L12         0x109eef620 EXT_STMT                                                                               /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
>00012:     global $i;
 00013:     $i += 3;
 00014:     echo "This is testFunc! i:" . $i, PHP_EOL;

prompt> s
[L12         0x109eef640 BIND_GLOBAL             $i                   "i"                                       /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
[L13         0x109eef660 EXT_STMT                                                                               /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
>00013:     $i += 3;
 00014:     echo "This is testFunc! i:" . $i, PHP_EOL;
 00015: }

间接进行了两次 s 单步,能够看到 global $i 对应的 opcode 操作是 BIND_GLOBAL 。持续向下操作。

prompt> s
[L13         0x109eef680 ASSIGN_ADD              $i                   3                                         /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
[L14         0x109eef6a0 EXT_STMT                                                                               /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
>00014:     echo "This is testFunc! i:" . $i, PHP_EOL;
 00015: }
 00016: 

prompt> s
[L14         0x109eef6c0 CONCAT                  "This is testFunc!"+ $i                   ~1                   /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
[L14         0x109eef6e0 ECHO                    ~1                                                             /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
This is testFunc! i:4
[L14         0x109eef700 EXT_STMT                                                                               /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
[L14         0x109eef720 ECHO                    "\n"                                                           /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]

[L15         0x109eef740 EXT_STMT                                                                               /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php]
>00015: }
 00016: 
 00017: testFunc();

第 13 行执行的是 $i += 3 的操作,对应的 opcode 操作是 ASSIGN_ADD ,减少的值是 3 。持续 s 后执行了第 14 行,留神这里进行了两步操作。一次是 CONCAT ,一次是 ECHO ,而后代码失常输入了打印进去的语句。

从下面的几步调试能够清晰的看到 PHP 在 opcode 层面的一步步的执行状态,就像 XDebug 一样,每一次的执行都会有相干的变量、操作的信息输入。

类函数断点设置

类函数的断点设置其实就和下面的办法断点函数一样,十分的简略不便。

class A{
    function testFuncA(){
        echo "This is class A testFuncA!", PHP_EOL;
    }
}
$a = new A;
$a->testFuncA();
phpdbg_break_method('A', 'testFuncA');

这里就不贴出调试的代码了,大家能够本人尝试一下。

命令行减少断点

除了在 PHP 代码中给出固定的断点之外,咱们还能够在命令行中进行断点的减少,比方咱们去掉之前的办法断点函数。而后在命令行中指定在办法中减少一个断点。

prompt> b testFunc#3
[Breakpoint #1 added at testFunc#3]
3 这是什么意思呢?其实就是说咱们在这个办法体外部的第 3 行减少一个断点。也就是说,咱们在 $i += 3; 这一行减少了一个断点。行数是从办法定义那一行开始算的并且是从 1 开始,如果不加这个行数,就是间接从办法定义那一行开始。
prompt> r
[Breakpoint #0 resolved at testFunc#3 (opline 0x1050ef660)]
[Breakpoint #0 resolved at testFunc#3 (opline 0x1050ef660)]
[Breakpoint #0 resolved at testFunc#3 (opline 0x1050ef660)]
[Breakpoint #0 resolved at testFunc#3 (opline 0x1050ef660)]
[Breakpoint #0 in testFunc()#3 at /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202006/source/PHPDebug互动扩大.php:13, hits: 1]
>00013:     $i += 3;
 00014:     echo "This is testFunc! i:" . $i, PHP_EOL;
 00015: }

执行 r 后,咱们就间接定位到了 testFun() 办法中的第三行。

总结

明天咱们只是简略的学习了一下 phpdbg 这个工具的应用。从 help 命令中就能够看出,这个工具还有十分多的选项参数,能够帮咱们实现许多调试工作。在这里只是跟大家一起入个门,未来在学习的过程中再次接触到的时候咱们再持续深刻的钻研。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202006/source/PHPDebug%E4%BA%92%E5%8A%A8%E6%89%A9%E5%B1%95.php

参考文档:

https://www.php.net/manual/zh/intro.phpdbg.php

各自媒体平台均可搜寻【硬核项目经理】


推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了三种方法来实现在Win7系统中显示桌面的快捷方式,包括使用任务栏快速启动栏、运行命令和自己创建快捷方式的方法。具体操作步骤详细说明,并提供了保存图标的路径,方便以后使用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 本文介绍了在MySQL8.0中如何查看性能并解析SQL执行顺序。首先介绍了查询性能工具的开启方法,然后详细解析了SQL执行顺序中的每个步骤,包括from、on、join、where、group by、having、select distinct、union、order by和limit。同时还介绍了虚拟表的概念和生成过程。通过本文的解析,读者可以更好地理解MySQL8.0中的性能查看和SQL执行顺序。 ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法
    本文介绍了修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法。首先解释了UEFI的概念和作用,然后提供了两种解决方法。第一种方法是在bios界面中将Boot Mode设置为Legacy Support,Boot Priority设置为Legacy First,并关闭UEFI。第二种方法是使用U盘启动盘进入PE系统,运行磁盘分区工具DiskGenius,将硬盘的分区表设置为gpt格式,并留出288MB的内存。最后,通过运行界面输入命令cmd来完成设置。 ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
author-avatar
看看2502895567
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有