用c写php的扩展不是一件轻松的事情,调试起来更是麻烦。普通的php扩展调试网上可以找到资料。我这里因为要用到c++,因此用了phpx来降低php扩展开发的门槛。
phpx项目地址:https://github.com/swoole/phpx
准备环境
ubuntu16.04, gcc, git, wget
首先从php的官方网站下载需要的php版本的源代码: https://php.net/releases/
我下载的是php-7.0版本的
wget https://www.php.net/distributions/php-7.0.33.tar.gz
下载完成后,解压进入目录,安装一些必要的依赖库。
sudo apt-get install libxml2-dev
./configure --enable-debug
make -j 4
sudo make install
因为我的扩展使用了phpx这个库,所有phpx的编译也需要开启debug模式,编辑cmakelist.txt加入
SET(CMAKE_BUILD_TYPE "Debug")
。然后
cmake .
make -j 4
sudo make install
注意:在编译php扩展的时候也要开启调试模式。
使用gdb调试
因为php+phpx这个组合编译出来的扩展没有办法像普通的gdb调试一样,通过行号来打断点调试。因此需要根据函数名来打断点。
比如我的代码中有一个关键的方法名叫做input, 因此可以
nm /usr/local/lib/php/extensions/debug-non-zts-20151012/php_dv.so | grep input
得到以下的查找结果
000000000003a99e T _Z8Dv_inputRN3php6ObjectERNS_4ArgsERNS_7VariantE
00000000000491f8 T _ZN11DataAdaptor5inputESt6vectorIP6PersonSaIS2_EE
_ZN11DataAdaptor5inputESt6vectorIP6PersonSaIS2_EE
这个就是可以打断点的函数名啦。
gdb php
break _ZN11DataAdaptor5inputESt6vectorIP6PersonSaIS2_EE
run paintAll.php
就可以看到断点打在了
Breakpoint 1, DataAdaptor::input (this=0x1259de0,
allPerson=std::vector of length 2622, capacity 2622 = {...}) at ../DataAdaptor.cc:195
195 void DataAdaptor::input(vector allPerson) {
可以使用layout分割窗口,大致结果如下:
coredump信息的查看
php扩展出错后,也可以生成coredump文件。需要修改limits.conf中的core文件大小,比如设置成unlimited。生成core文件后,执行gdb php core
, 然后使用bt即可打印出方法的调用栈,从而分析问题出现的原因。