[C++]GDB调试C++类

GDB调试C++类

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

时间: 2024-10-29 19:06:21

[C++]GDB调试C++类的相关文章

gdb调试命令

本篇摘自互联网,纯属自己学习笔记,然分享给看到我的博客的人们. 用GDB调试程序 GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本.UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优势在于,它们可以非常容易的集成在一起,使用几个简单的已有工具的命令,就可以做出一个非常强大的功能. 于是UNIX下的软件比Windows下的软件更能有机地结合,各自发挥各自的长处,组合成更为强劲的功能.而Windows下的图形软件基本上是各自为营,

GDB调试core dump文件示例

上篇论述了三层的基本概念,作用,关系,现在展示下系统中用户登陆过程中简单应用三层结构设计思想. vb.NET的操作如下 首先建立以下windows应用程序以及类库 首先建立实体类 Public Class userInfo Private _username As String Public Property UserName As String Get Return _username End Get Set(ByVal value As String) _username = value E

gdb调试行号错位

http://blog.csdn.net/wangxmin2005/article/details/8128192 gdb调试过程中出现行号错位的情况,原因一般有两个: 1. 编译器的优化可能把某些语句给优化掉了. 解决这种情况很简单,makefile中-O2这类的编译优化去掉,换成最简单的g++ -g $^ -o [email protected] $(INCLUDES) $(LIBS) 2.文件格式转换问题.dos格式文件传输到unix系统时,会在每行的结尾多一个^M,造成文件格式混乱,换行

@清晰掉 GDB调试器中的战斗机

GDB 的命令很多,本文不会全部介绍,仅会介绍一些最常用的.在介绍之前,先介绍GDB中的一个非常有用的功能:补齐功能.它就如同Linux下SHELL中的命令补齐一样.当你输入一个命令的前几个字符,然后输入TAB键,如果没有其它命令的前几个字符与此相同,SHELL将补齐此命令.如果有其它命令的前几个字符与此相同,你会听到一声警告声,再输入TAB键,SHELL将所有前几个字符与此相同的命令全部列出.而GDB中的补齐功能不仅能补齐GDB命令,而且能补齐参数. 本文将先介绍常用的命令,然后结合一个具体的

GDB Core,gdb 调试大全,core文件调试

编译: gcc -g -o hello hello.c gdb 调试: 基本 gdb 命令. 命 令 描 述 小结:常用的gdb命令 backtrace 显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where) breakpoint 在程序中设置一个断点 cd 改变当前工作目录 clear 删除刚才停止处的断点 commands 命中断点时,列出将要执行的命令 continue 从断点开始继续执行 delete 删除一个断点或监测点:也可与其他命令一起使用 display 程序停

gdb调试汇总

1. 启动GDB开始调试: (1)gdb program ///最常用的用gdb启动程序,开始调试的方式(2)gdb program core ///用gdb查看core dump文件,跟踪程序core的原因(3)gdb program pid ///用gdb调试已经开始运行的程序,指定pid即可 2. 应用程序带命令行参数的情况,可以通过下面两种方法启动: (1)启动GDB的时候,加上–args选项,然后把应用程序和其命令行参数带在后面,具体格式为:gdb –args program args

用GDB 调试Java程序

陈皓 http://blog.csdn.net/haoel 背景 想要使用GDB调试程序,就需要用GNU的编译器编译程序.如:用GCC编译的C/C++的程序,才能用GDB调试.对于Java程序也是一样的,如果想要用GDB调试,那么就需要用GNU的Java编译器--GCJ来编译Java程序. 目前,很多Linux都不会预装Sun的JVM,取而代之是使用GNU的开源编译器来编译和运行Java程序.比如RedHat和Ubuntu,其默认安装都是使用GNU的Java编译器(gcj)和解释器(gij).当

CentOS环境下,gdb调试中出现:Missing separate debuginfos, use: debuginfo-install.....的问题

在gdb调试时segmentation fault问题时,遇到下面的了问题: Program received signal SIGABRT, Aborted.0x00007ffff73eb925 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:6464 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);Missing separate debuginfos, use:

比较全面的gdb调试命令

用GDB调试程序 GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本.UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优势在于,它们可以非常容易的集成在一起,使用几个简单的已有工具的命令,就可以做出一个非常强大的功能. 于是UNIX下的软件比Windows下的软件更能有机地结合,各自发挥各自的长处,组合成更为强劲的功能.而Windows下的图形软件基本上是各自为营,互相不能调用,很不利于各种软件的相互集成.在这里并不是要和Win