热门标签 | 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

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


推荐阅读
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • Python处理Word文档的高效技巧
    本文详细介绍了如何使用Python处理Word文档,涵盖从基础操作到高级功能的各种技巧。我们将探讨如何生成文档、定义样式、提取表格数据以及处理超链接和图片等内容。 ... [详细]
  • 在现代Web应用中,当用户滚动到页面底部时,自动加载更多内容的功能变得越来越普遍。这种无刷新加载技术不仅提升了用户体验,还优化了页面性能。本文将探讨如何实现这一功能,并介绍一些实际应用案例。 ... [详细]
  • 本文介绍如何在华为CE交换机上配置M-LAG(多链路聚合组),以实现CE1和CE2设备作为VLAN 10网关的高可用性。通过详细的配置步骤,确保网络冗余和稳定性。 ... [详细]
  • 本文详细介绍了如何使用 MySQL 查询特定时间段的数据,包括今天、本周、上周、本月和上个月的数据。适合对 MySQL 查询感兴趣的读者。 ... [详细]
  • 深入解析Redis内存对象模型
    本文详细介绍了Redis内存对象模型的关键知识点,包括内存统计、内存分配、数据存储细节及优化策略。通过实际案例和专业分析,帮助读者全面理解Redis内存管理机制。 ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 本文介绍如何使用 Android 的 Canvas 和 View 组件创建一个简单的绘图板应用程序,支持触摸绘画和保存图片功能。 ... [详细]
  • 本文详细解析了Java中hashCode()和equals()方法的实现原理及其在哈希表结构中的应用,探讨了两者之间的关系及其实现时需要注意的问题。 ... [详细]
  • 本文深入探讨了SQL数据库中常见的面试问题,包括如何获取自增字段的当前值、防止SQL注入的方法、游标的作用与使用、索引的形式及其优缺点,以及事务和存储过程的概念。通过详细的解答和示例,帮助读者更好地理解和应对这些技术问题。 ... [详细]
  • 主板IO用W83627THG,用VC如何取得CPU温度,系统温度,CPU风扇转速,VBat的电压. ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 本文介绍了如何在 C# 和 XNA 框架中实现一个自定义的 3x3 矩阵类(MMatrix33),旨在深入理解矩阵运算及其应用场景。该类参考了 AS3 Starling 和其他相关资源,以确保算法的准确性和高效性。 ... [详细]
  • 在网站制作中随时可用的10个 HTML5 代码片段
    HTML很容易写,但创建网页时,您经常需要重复做同样的任务,如创建表单。在这篇文章中,我收集了10个超有用的HTML代码片段,有HTML5启动模板、空白图片、打电话和发短信、自动完 ... [详细]
  • SDN网络拓扑发现机制解析
    本文深入探讨了SDN(软件定义网络)中拓扑发现的原理与实现方法,重点介绍了LLDP协议在OpenFlow环境中的应用,并讨论了非OpenFlow设备存在时的链路发现策略。 ... [详细]
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社区 版权所有