首页 / C++ / [C++]GDB调试C++类
[C++]GDB调试C++类
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了[C++]GDB调试C++类,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4937字,纯文字阅读大概需要8分钟。
内容图文
![[C++]GDB调试C++类](/upload/InfoBanner/zyjiaocheng/473/17bc371c126f45c8ae504030aed1d9ef.jpg)
Linux上调试常用的工具就是gdb了。借助学习C++虚函数表和内存布局的机会顺便学习下gdb常规调试技巧。
一,测试用例
1,C++头文件(szyu_test_gdb.h)
/****************************** * * Author : szyu * * Date : 2016.10.25 * ********************************/ #ifndef __SZYU_GDB__ #define __SZYU_GDB__ #include <iostream> class Base { public: Base() { }; Base( int v ) : non_static_member1( v ) { }; virtual ~Base() { }; public: void non_static_func1() { std::cout << "In non_static_func1()" << std::endl; } static void static_func1() { std::cout << "In static_func1()" << std::endl; } virtual void virtual_func1() { std::cout << "In virtual_func1()" << std::endl; } private: int non_static_member1; static int static_member1; }; int Base::static_member1 = 99; #endif
2,C++测试用例(szyu_test_gdb.cpp)
/************************ * * Author : szyu * * Date : 2016.10.25 * ******************************/ #include "szyu_test_gdb.h" void test1() { /* 静态函数访问 */ Base::static_func1(); /* 创建对象 */ Base bb( 57 ); /* 非静态函数访问 */ bb.non_static_func1(); /* 虚函数访问 */ bb.virtual_func1(); } int main( int argc, char *argv[] ) { test1(); return 0; }
二,调试
1,gdb调试前需编译生成可执行文件,并且需把调试信息加到可执行文件中。-g参数可以做到这点。使用方法为:g++ -g szyu_test_gdb.cpp(默认生成a.out可执行文件)
2,启动gdb调试:gdb a.out
3,设置断点,可获取运行时的堆栈信息。
分别对以下位置设置了断点:
1)构造函数:Base( int v )
2)虚析构函数:virtual ~Base()
3)静态函数调用:bb.static_func1()
4)非静态函数调用:bb.non_static_func1()
5)虚函数调用:bb.virtual_func1()
4,运行程序,遇到第一个断点:静态函数调用。单步跟踪s(step)命令进入函数内部,并打印地址如下:
5,c(continue)恢复程序运行,接下来程序停在第二断点处,即Base(int v)构造函数处。打印Base类对象bb如下:
由图可以类对象的地址为:0x7fffffffe320
对对象首地址进行解引用得到地址:0x400cb0即为虚函数表地址,故可知在该编译器中的虚函数表位于对象实例的最前端。
从打印的Base类对象可知,此时虚函数表已创建,且虚函数表地址为0x400cb0。对于静态成员和非静态成员都已初始化好了。此时获取虚函数表中的内容如下所示:
由于虚函数表是二级指针。所以使用void **转换。再使用解引用运算符变成一级指针。
其中还涉及到set print array,@和/a三个知识点:
1)默认数组显示是关闭状态的(即打印数组时,每个元素则以逗号分隔)。打开数组显示状态后,每个元素占一行打印。
2)p /a 打印语句中a只是参数选项之一,常见该参数如下:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
3)“@”的左边是第一个内存的地址的值,“@”的右边则你你想查看内存的长度。上图中的4代表打印出四段内存长度。此处由于虚函数表中总共存了三个虚函数内存段地址,故最后一个值是随机数。
为了支持RTTI(Run Time Type Identification,运行时类型识别),在虚函数表前存放了type_info指针。
而静态成员变量和非静态成员变量获取如下:
6,c(continue)继续运行,接下来程序停留在第三个断点处,即非静态方法调用。
7,c(continue)继续运行,接下来程序停留在第四个断点处,即虚函数调用。
由打印出来的虚函数地址可知:该地址与虚函数表中存的地址一致。
8,c(continue)继续运行,接下来程序停留在第五个断点处,即虚析构函数。
通过info line查看地址与虚函数表一致。
本文gdb调试命令主要参考:http://blog.csdn.net/haoel/article/details/2879
本文出自 “11988200” 博客,请务必保留此出处http://11998200.blog.51cto.com/11988200/1866100
[C++]GDB调试C++类
标签:c++ gdb
本文系统来源:http://11998200.blog.51cto.com/11988200/1866100
内容总结
以上是互联网集市为您收集整理的[C++]GDB调试C++类全部内容,希望文章能够帮你解决[C++]GDB调试C++类所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。