每天学点GDB(五)

使用GDB来进行STL容器的调试

现代C++中STL使用的越来越普遍,较之其它类型,stl容器类的调试显得复杂度更好。本篇以map为例说明如何利用gdb来遍历map中的各成员变量。

源码如下:

#include <map>
#include <iostream>
#include <string>

using namespace std;

int main(int arg, char** argv) {
  map<int, string> mapExample;
  mapExample.insert(pair<int,string>(1,"demo_one"));
  mapExample.insert(pair<int,string>(2,"demo_two"));
  mapExample.insert(pair<int,string>(3,"demo_three"));
  map<int,string>::iterator iter;
  for ( iter = mapExample.begin();iter!=mapExample.end();iter++) {
    cout<<iter->second<<endl;
  }
  return 0;
}

编译运行:

g++ -o demo -g stl_test.cpp

运行

gdb ./demo
br 14
r

显示mapExample容器中的各个元素

p mapExample
$1 = std::map with 3 elements = {[1] = "demo_one", [2] = "demo_two", [3] = "demo_three"}

如果想要知道每个element的所在的内存区域,需要先得到stl map的类型。

ptype mapExample

显示如下,成员函数部分略去。

type = class std::map<int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<int>, std::allocator<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > [with _Key = int,
         _Tp = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Compare = std::less<int>,
         _Alloc = std::allocator<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >] {
  private:
    _Rep_type _M_t;

至此关键性成员变量显示即_M_t

顺着这条思路继续往下,查看_M_t的结构定义

p mapExample._M_t

结果显示出stl map实现使用了红黑二叉树rb-tree

  _M_impl = {
    <std::allocator<std::_Rb_tree_node<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >> = {
      <__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >> = {<No data fields>}, <No data fields>},
    members of std::_Rb_tree<int, std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<int>, std::allocator<std::pair<int const, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_Rb_tree_impl<std::less<int>, false>:
    _M_key_compare = {
      <std::binary_function<int, int, bool>> = {<No data fields>}, <No data fields>},
    _M_header = {
      _M_color = std::_S_red,
      _M_parent = 0x6040b0,
      _M_left = 0x604040,
      _M_right = 0x604120
    },
    _M_node_count = 3
  }
}

至此,事情变的简单了,利用_M_left和_M_right就可以遍历各个二叉树结点了。

手工方式作一次不会觉着很累,但次次都手工查看会觉着不厌其烦。幸运的是,早有人已经提供了自动化的脚本。具体链接如下

https://gist.github.com/skyscribe/3978082

使用方法是将上述链接中的内容保存到~/.gdbinit中,如果没有.gdbinit就手工创建一个,该文件在gdb每次启动时会被最先读入。

有了上述脚本,就可以用plist, pmap, pvector来遍历stl容器了。

时间: 2024-10-14 02:09:17

每天学点GDB(五)的相关文章

从零开始学Xamarin.Forms(五) 技巧

原文:从零开始学Xamarin.Forms(五) 技巧        由于HTML5规范于2014年10月终于定稿,公司.net开发人员较少,国内外已有了较为成熟的UI框架.手机软件硬件的快速发展等等原因,所以我就不打算再使用Xamarin了,而是采用HTML5+CSS3+Javascript的方式来进行跨平台的开发.之前在探索Xamarin中积累了一些小经验也同时分享给大家,希望能给大家带来帮助. 1.TabbedPage中嵌入NavigationPage,NavigationPage中的Ro

10天学安卓-第五天

原文:10天学安卓-第五天 经过前几天的练习,相信大家已经对如何做出一个简单的界面有了初步的了解,并且已经做出来一个还不错的天气列表了. 今天大家稍事休息,要练习的内容比较少,着重学习一些理论知识,先理清几个概念. Android系统架构 Android系统本质上是Linux系统,但相对于Linux系统,主要在驱动.性能.内存管理.设备管理等一些部分做了比较多的改动,以更适用于移动设备. 从上图可以看到,Android系统架构为四层,分别是Linux内核.系统运行库.应用程序框架以及应用层,每一

[老老实实学WCF] 第五篇 再探通信--ClientBase

原文:[老老实实学WCF] 第五篇 再探通信--ClientBase 老老实实学WCF 第五篇 再探通信--ClientBase   在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创建了通道,实现了和服务端的通信.然而,与服务端通信的编程模型不只一种,今天我们来学习利用另外一个服务类ClientBase<>来完成同样的工作,了解了这个类的使用方法,我们对服务引用中的关键部分就能够理解了.   Client

每天学点GDB(六)

<一>如何利用gdb对coredump进行分析 本篇主要讲解如何利用gdb对coredump进行分析 gdb ./demo core 查看调用堆栈 gdb)bt 查看更为完整的信息 gdb) bt full 如果是多线程,想看每个线程的调用堆栈 gdb) thread apply all bt 至于如何分析内存变量之类的,在本一系列前面的章节有专门论述,可以参考. 想调试已经在运行的程序 gdb ./demo 假设当前运行着的demo进程为1234,则在gdb中运行attach进行关联 gdb

为SOUNDWAVE设计WATCH应用时学到的五个技巧

  Soundwave已经在iOS及Android平台上发展了将近两年.我(英文原文作者)最近有幸得到机会,能够为Apple Watch版本的Soundwave进行UI与交互设计,使其成为4月24日之后Watch平台上的首批第三方应用之一. 为Apple Watch这样的新平台设计app,这对于我们的设计与开发团队来说都是绝佳的学习机会.作为设计师,我在这个过程当中学到了一些很关键的东西. 一.学习设计规范 官方的 Apple Watch人机界面设计规范 很严格.其实iOS版本的也是如此,只是这

跟我学SQL:(五)创建和修改表格

创建 再次欢迎您来到SQL(结构化查询语言)基础系列教程.本文将介绍数据库定义语言(DDL)用于创建数据库和表格以及修改表格结果的指令.    当你使用这些指令时一定要小心--它很容易删去你的数据库中的主要结构令您丢失数据.所以,在您开始修改数据库之前,您需要知道数据库是什么. -------------------------------------------------------------------------------- 数据库之间的差异 本文中的样品查询系统遵循SQL92 IS

坚持学asp.net——(五)

asp.net c#中的数据字符类型: string不能存储在堆栈中,显然属于引用类型:char则明显属于值类型. 字符串类型: 声明一个字符串类型时,不是在堆中创建一个字符串对象,而只是在堆栈中创建了一个字符串的引用,还没有引用字符串对象. 不包含任何字符的字符串,称为空字符串. char(字符)类型: 将文本以数的形式存储,将单个的字符放在char的变量中,且它存储为一个0~65535之间的16位数值形式,表示一个unicode字符. 转义字符: \' 单引号 \" 双引号 \\ 斜杠 \0

每天学点GDB(一)

<一>简单示例--Hello World 在Linux环境下进行C或是C++编程,调试工具首选GDB. GDB的功能很多,一下子全弄明白似乎不太可能.那么就从最简单的使用说起吧.一谈起简单,Helloworld就成了最佳的选择了. #include <stdio.h> #include <stdlib.h> 4 int main(int argc, char** argv) { printf("hello,world\n"); return 0; }

每天学点GDB(二)

<一>如何让将调试的内容保存到外部文件里面 在上一篇提及如何在断点处打印调试信息后,程序自动继续执行.本节主要讲述如何让将调试的内容保存到外部文件里面. 默认情况下,日志是没有打开的,所有的调试信息都会在屏幕中显示,即默认是输出到stdout中的.那么有没有可能将输出到屏幕中的内容保存到文件里呢.答案自然是肯定的,这里面有个地方遇要注意一下子,具体会在下面的示例中提及. 将日志文件打开,不指定文件名的话,默认的文件名是gdb.txt. gdb)set logging on 查看更多有关logg