• 《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 <_Unwind_Resume@plt>
    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
    

    可用下图表示:

    可知,特征是没有问题


  • 相关阅读:
    Emmet 语法
    GitHub常用命令
    ProgressBar.js – 漂亮的响应式 SVG 进度条
    99个漂亮的注册和登录页设计(附PSD)
    android Acitivity之间的几种传值方式(^_^)
    Android 动态生成 EditTest
    Android 小笔记
    winfrom获取用户控件里的控件对象
    MVC+Easeyui dialog的小问题
    bootStrap
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/6936192.html
Copyright © 2020-2023  润新知