《coredump问题原理探究》Linux x86版7.7节 set对象

看一下bits/stl_map和bits/stl_set可以看到map和set的定义如下:

84   template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
 85             typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
 86     class map
 87     {
 88     public:
 89       typedef _Key                                          key_type;
 90       typedef _Tp                                           mapped_type;
 91       typedef std::pair<const _Key, _Tp>                    value_type;
 92       typedef _Compare                                      key_compare;
 93       typedef _Alloc                                        allocator_type;
 94
 95     private:
 96       // concept requirements
 97       typedef typename _Alloc::value_type                   _Alloc_value_type;
 98       __glibcxx_class_requires(_Tp, _SGIAssignableConcept)
 99       __glibcxx_class_requires4(_Compare, bool, _Key, _Key,
100                 _BinaryFunctionConcept)
101       __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept)
102
103     public:
104       class value_compare
105       : public std::binary_function<value_type, value_type, bool>
106       {
107     friend class map<_Key, _Tp, _Compare, _Alloc>;
108       protected:
109     _Compare comp;
110
111     value_compare(_Compare __c)
112     : comp(__c) { }
113
114       public:
115     bool operator()(const value_type& __x, const value_type& __y) const
116     { return comp(__x.first, __y.first); }
117       };
118
119     private:
120       /// This turns a red-black tree into a [multi]map.
121       typedef typename _Alloc::template rebind<value_type>::other
122         _Pair_alloc_type;
123
124       typedef _Rb_tree<key_type, value_type, _Select1st<value_type>,
125                key_compare, _Pair_alloc_type> _Rep_type;
126
127       /// The actual tree structure.
128       _Rep_type _M_t;
85   template<typename _Key, typename _Compare = std::less<_Key>,
 86        typename _Alloc = std::allocator<_Key> >
 87     class set
 88     {
 89       // concept requirements
 90       typedef typename _Alloc::value_type                   _Alloc_value_type;
 91       __glibcxx_class_requires(_Key, _SGIAssignableConcept)
 92       __glibcxx_class_requires4(_Compare, bool, _Key, _Key,
 93                 _BinaryFunctionConcept)
 94       __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept)
 95
 96     public:
 97       // typedefs:
 98       //@{
 99       /// Public typedefs.
100       typedef _Key     key_type;
101       typedef _Key     value_type;
102       typedef _Compare key_compare;
103       typedef _Compare value_compare;
104       typedef _Alloc   allocator_type;
105       //@}
106
107     private:
108       typedef typename _Alloc::template rebind<_Key>::other _Key_alloc_type;
109
110       typedef _Rb_tree<key_type, value_type, _Identity<value_type>,
111                key_compare, _Key_alloc_type> _Rep_type;
112       _Rep_type _M_t;  // Red-black tree representing set.
113

由于map,set的本身定义都是声明任何成员变量,所有成员变量都是从_Rb_tree继承过来的,唯一的差别只是_Rb_tree最后参数的定义不一样.

set的特征如下:

1.     set对象有五个成员_M_node_count标明map有多少个元素,三个指针分别指向树中最左的节点,树的根节点,树的最右节点,_M_color表明是红树还是黑树,_M_key_compare指向比较函数

2.     树的根节点的_M_parent指向头节点

3.     每一个节点的值都紧跟着_M_right

看一下例子:

  1 #include <set>
  2
  3 int main()
  4 {
  5     std::set<int> iSet;
  6     iSet.insert( 0x523 );
  7     iSet.insert( 0x352 );
  8     iSet.insert( 0x808 );
  9
 10     return 0;
 11 }

看一下main函数的汇编:

(gdb) disassemble main
Dump of assembler code for function main:
   0x08048634 <+0>:	lea    0x4(%esp),%ecx
   0x08048638 <+4>:	and    $0xfffffff0,%esp
   0x0804863b <+7>:	pushl  -0x4(%ecx)
   0x0804863e <+10>:	push   %ebp
   0x0804863f <+11>:	mov    %esp,%ebp
   0x08048641 <+13>:	push   %esi
   0x08048642 <+14>:	push   %ebx
   0x08048643 <+15>:	push   %ecx
   0x08048644 <+16>:	sub    $0x5c,%esp
   0x08048647 <+19>:	lea    -0x54(%ebp),%eax
   0x0804864a <+22>:	mov    %eax,(%esp)
   0x0804864d <+25>:	call   0x8048712 <_ZNSt3setIiSt4lessIiESaIiEEC2Ev>
   0x08048652 <+30>:	movl   $0x523,-0x34(%ebp)
   0x08048659 <+37>:	lea    -0x3c(%ebp),%eax
   0x0804865c <+40>:	lea    -0x34(%ebp),%edx
   0x0804865f <+43>:	mov    %edx,0x8(%esp)
   0x08048663 <+47>:	lea    -0x54(%ebp),%edx
   0x08048666 <+50>:	mov    %edx,0x4(%esp)
   0x0804866a <+54>:	mov    %eax,(%esp)
   0x0804866d <+57>:	call   0x804878c <_ZNSt3setIiSt4lessIiESaIiEE6insertERKi>
   0x08048672 <+62>:	sub    $0x4,%esp
   0x08048675 <+65>:	movl   $0x352,-0x28(%ebp)
   0x0804867c <+72>:	lea    -0x30(%ebp),%eax
---Type <return> to continue, or q <return> to quit---
   0x0804867f <+75>:	lea    -0x28(%ebp),%edx
   0x08048682 <+78>:	mov    %edx,0x8(%esp)
   0x08048686 <+82>:	lea    -0x54(%ebp),%edx
   0x08048689 <+85>:	mov    %edx,0x4(%esp)
   0x0804868d <+89>:	mov    %eax,(%esp)
   0x08048690 <+92>:	call   0x804878c <_ZNSt3setIiSt4lessIiESaIiEE6insertERKi>
   0x08048695 <+97>:	sub    $0x4,%esp
   0x08048698 <+100>:	movl   $0x808,-0x1c(%ebp)
   0x0804869f <+107>:	lea    -0x24(%ebp),%eax
   0x080486a2 <+110>:	lea    -0x1c(%ebp),%edx
   0x080486a5 <+113>:	mov    %edx,0x8(%esp)
   0x080486a9 <+117>:	lea    -0x54(%ebp),%edx
   0x080486ac <+120>:	mov    %edx,0x4(%esp)
   0x080486b0 <+124>:	mov    %eax,(%esp)
   0x080486b3 <+127>:	call   0x804878c <_ZNSt3setIiSt4lessIiESaIiEE6insertERKi>
   0x080486b8 <+132>:	sub    $0x4,%esp
   0x080486bb <+135>:	mov    $0x0,%ebx
   0x080486c0 <+140>:	lea    -0x54(%ebp),%eax
   0x080486c3 <+143>:	mov    %eax,(%esp)
   0x080486c6 <+146>:	call   0x80486fe <_ZNSt3setIiSt4lessIiESaIiEED2Ev>
   0x080486cb <+151>:	mov    %ebx,%eax
   0x080486cd <+153>:	lea    -0xc(%ebp),%esp
   0x080486d0 <+156>:	add    $0x0,%esp
---Type <return> to continue, or q <return> to quit---
   0x080486d3 <+159>:	pop    %ecx
   0x080486d4 <+160>:	pop    %ebx
   0x080486d5 <+161>:	pop    %esi
   0x080486d6 <+162>:	pop    %ebp
   0x080486d7 <+163>:	lea    -0x4(%ecx),%esp
   0x080486da <+166>:	ret
   0x080486db <+167>:	mov    %edx,%ebx
   0x080486dd <+169>:	mov    %eax,%esi
   0x080486df <+171>:	lea    -0x54(%ebp),%eax
   0x080486e2 <+174>:	mov    %eax,(%esp)
   0x080486e5 <+177>:	call   0x80486fe <_ZNSt3setIiSt4lessIiESaIiEED2Ev>
   0x080486ea <+182>:	mov    %esi,%eax
   0x080486ec <+184>:	mov    %ebx,%edx
   0x080486ee <+186>:	mov    %eax,(%esp)
   0x080486f1 <+189>:	call   0x8048564 <[email protected]>
End of assembler dump.

由上面汇编可知,ebp-0x54是set的this指针.

在0x080486b8指令地址打断点,验证一下set的特征是不是对的.

(gdb) x /8wx $ebp-0x54
0xbffff234:	0xbffff270	0x00000000	0x0804b008	0x0804b020
0xbffff244:	0x0804b038	0x00000003	0x0804b008	0xbffff201
(gdb) x /8wx 0x0804b008
0x804b008:	0x00000001	0xbffff238	0x0804b020	0x0804b038
0x804b018:	0x00000523	0x00000019	0x00000000	0x0804b008
(gdb) x /8x 0x0804b020
0x804b020:	0x00000000	0x0804b008	0x00000000	0x00000000
0x804b030:	0x00000352	0x00000019	0x00000000	0x0804b008
(gdb) x /8wx 0x0804b038
0x804b038:	0x00000000	0x0804b008	0x00000000	0x00000000
0x804b048:	0x00000808	0x00020fb9	0x00000000	0x00000000

可用下图表示:

可知,特征是没有问题

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-26 18:43:07

《coredump问题原理探究》Linux x86版7.7节 set对象的相关文章

《coredump问题原理探究》Linux x86版7.5节 Map对象

先看一个例子: 1 #include <map> 2 3 int main() 4 { 5 std::map<int,int> iMap; 6 7 iMap[5] = 6; 8 iMap[8] = 20; 9 iMap[2] = 80; 10 11 return 0; 12 } 看一下汇编: (gdb) disassemble main Dump of assembler code for function main: 0x080486e4 <+0>: push %eb

《coredump问题原理探究》Linux x86版7.3节List对象

先看一下例子: 1 #include <list> 2 3 int main() 4 { 5 std::list<int> lst; 6 7 lst.push_back( 0x12345678 ); 8 lst.push_front( 0xabcdef01 ); 9 lst.push_back( 0x24242522 ); 10 11 return 0; 12 } 再看一下汇编: (gdb) disassemble main Dump of assembler code for f

《coredump问题原理探究》Linux x86版7.1节vector对象

先看一下例子: 1 #include <vector> 2 3 int main() 4 { 5 std::vector<int> vec; 6 vec.push_back( 0xffeeffab ); 7 vec.push_back( 0xabcdef01 ); 8 vec.push_back( 0x12345678 ); 9 return 0; 10 } 看一下汇编: (gdb) b main Breakpoint 1 at 0x8048697 (gdb) r Starting

《coredump问题原理探究》Windows版 笔记

<coredump问题原理探究>Windows版 笔记 Debug 一.环境搭建 1.Win7捕获程序dump 2.Windbg符号表设置(Symbols Search Path) 二.WinDbg命令 三.函数栈帧 1.栈内存布局 2.栈溢出 3.栈的规律 4.定位栈溢出问题的经验方法 四.函数逆向 五.C内存布局 1.基本类型 2.数组类型 3.结构体 六.C++内存布局 1.类的内存布局 2.this指针 3.虚函数表及虚表指针 4.单继承 5.多继承(无公共基类) 七.STL容器内存布

《coredump问题原理探究》Linux x86版6.3节有成员变量的类coredump例子

在探究完类成员变量分布后,来定位一个coredump例子来实践一把: (gdb) bt #0 0x0804863c in xuzhina_dump_c06_s2_ex::print() () #1 0x08048713 in main () 看一下xuzhina_dump_c06_s2_ex::print的汇编: (gdb) disassemble 0x0804863c Dump of assembler code for function _ZN22xuzhina_dump_c06_s2_ex

《coredump问题原理探究》Linux x86版7.2节vector coredump例子

看一个coredump的例子: [[email protected] s1_ex]$ gdb xuzhina_dump_c07_s1_ex core.27776 GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6) Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses

《coredump问题原理探究》Linux x86版6.2节C++风格数据结构内存布局之有成员变量的类

上面一节已经探究出this指针的辨别,由this指针就可以看到类的内容.在这里,就由this指针来看一下类的成员变量是如何排列. 先看一个例子 1 #include <stdio.h> 2 class xuzhina_dump_c06_s2 3 { 4 private: 5 short m_c; 6 char m_d; 7 int m_e; 8 9 public: 10 xuzhina_dump_c06_s2( int a, int b ) 11 { 12 m_c = (short)(a +

《coredump问题原理探究》Linux x86版6.8节多继承coredump例子

下面看一个coredump的例子: (gdb) bt #0 0x08048662 in xuzhina_dump_c06_s5_ex_child::inheritFrom(char*, int) () #1 0x08048609 in main () 先看一下xuzhina_dump_c06_s5_ex_child::inheritFrom的汇编: (gdb) disassemble 0x08048662 Dump of assembler code for function _ZN28xuzh

《coredump问题原理探究》Linux x86版6.1节C++风格数据结构内存布局之无成员变量的类

在探究完C风格数据结构内存布局之后,接着探究C++风格数据结构内存布局. 虽然最简单的类是没有任何成员变量和成员函数,但由于没什么意义,不值得探究.在这里,就先探究一下没有任何成员变量和虚函数,只有成员函数的类. 先看一下例子: 1 #include <stdio.h> 2 class xuzhina_dump_c06_s1 3 { 4 public: 5 void hello() 6 { 7 printf( "hello\n" ); 8 } 9 void print()