zoukankan      html  css  js  c++  java
  • 让gdb能打印C++中的容器类型

    由于原生的gdb对vector,map等容器的支持不太好,所以找到了一个工具,将这个工具集成到gdb中,就可以实现map,vector等容器的内容的打印操作。

    1。用vim将下方的代码拷贝到一个新的文件中,名为stl_views_1.0.3.gdb,这个是一个简单的工具的源码。

    #                                                                                                        
    #   STL GDB evaluators/views/utilities - 1.03
    #
    #   The new GDB commands:                                                         
    #         are entirely non instrumental                                             
    #         do not depend on any "inline"(s) - e.g. size(), [], etc
    #       are extremely tolerant to debugger settings
    #                                                                                 
    #   This file should be "included" in .gdbinit as following:
    #   source stl-views.gdb or just paste it into your .gdbinit file
    #
    #   The following STL containers are currently supported:
    #
    #       std::vector<T> -- via pvector command
    #       std::list<T> -- via plist or plist_member command
    #       std::map<T,T> -- via pmap or pmap_member command
    #       std::multimap<T,T> -- via pmap or pmap_member command
    #       std::set<T> -- via pset command
    #       std::multiset<T> -- via pset command
    #       std::deque<T> -- via pdequeue command
    #       std::stack<T> -- via pstack command
    #       std::queue<T> -- via pqueue command
    #       std::priority_queue<T> -- via ppqueue command
    #       std::bitset<n> -- via pbitset command
    #       std::string -- via pstring command
    #       std::widestring -- via pwstring command
    #
    #   The end of this file contains (optional) C++ beautifiers
    #   Make sure your debugger supports $argc
    #
    #   Simple GDB Macros writen by Dan Marinescu (H-PhD) - License GPL
    #   Inspired by intial work of Tom Malnar, 
    #     Tony Novac (PhD) / Cornell / Stanford,
    #     Gilad Mishne (PhD) and Many Many Others.
    #   Contact: dan_c_marinescu@yahoo.com (Subject: STL)
    #
    #   Modified to work with g++ 4.3 by Anders Elton
    #   Also added _member functions, that instead of printing the entire class in map, prints a member.
    
    
    
    #
    # std::vector<>
    #
    
    define pvector
        if $argc == 0
            help pvector
        else
            set $size = $arg0._M_impl._M_finish - $arg0._M_impl._M_start
            set $capacity = $arg0._M_impl._M_end_of_storage - $arg0._M_impl._M_start
            set $size_max = $size - 1
        end
        if $argc == 1
            set $i = 0
            while $i < $size
                printf "elem[%u]: ", $i
                p *($arg0._M_impl._M_start + $i)
                set $i++
            end
        end
        if $argc == 2
            set $idx = $arg1
            if $idx < 0 || $idx > $size_max
                printf "idx1, idx2 are not in acceptable range: [0..%u].
    ", $size_max
            else
                printf "elem[%u]: ", $idx
                p *($arg0._M_impl._M_start + $idx)
            end
        end
        if $argc == 3
          set $start_idx = $arg1
          set $stop_idx = $arg2
          if $start_idx > $stop_idx
            set $tmp_idx = $start_idx
            set $start_idx = $stop_idx
            set $stop_idx = $tmp_idx
          end
          if $start_idx < 0 || $stop_idx < 0 || $start_idx > $size_max || $stop_idx > $size_max
            printf "idx1, idx2 are not in acceptable range: [0..%u].
    ", $size_max
          else
            set $i = $start_idx
            while $i <= $stop_idx
                printf "elem[%u]: ", $i
                p *($arg0._M_impl._M_start + $i)
                set $i++
            end
          end
        end
        if $argc > 0
            printf "Vector size = %u
    ", $size
            printf "Vector capacity = %u
    ", $capacity
            printf "Element "
            whatis $arg0._M_impl._M_start
        end
    end
    
    document pvector
        Prints std::vector<T> information.
        Syntax: pvector <vector> <idx1> <idx2>
        Note: idx, idx1 and idx2 must be in acceptable range [0..<vector>.size()-1].
        Examples:
        pvector v - Prints vector content, size, capacity and T typedef
        pvector v 0 - Prints element[idx] from vector
        pvector v 1 2 - Prints elements in range [idx1..idx2] from vector
    end 
    
    #
    # std::list<>
    #
    
    define plist
        if $argc == 0
            help plist
        else
            set $head = &$arg0._M_impl._M_node
            set $current = $arg0._M_impl._M_node._M_next
            set $size = 0
            while $current != $head
                if $argc == 2
                    printf "elem[%u]: ", $size
                    p *($arg1*)($current + 1)
                end
                if $argc == 3
                    if $size == $arg2
                        printf "elem[%u]: ", $size
                        p *($arg1*)($current + 1)
                    end
                end
                set $current = $current._M_next
                set $size++
            end
            printf "List size = %u 
    ", $size
            if $argc == 1
                printf "List "
                whatis $arg0
                printf "Use plist <variable_name> <element_type> to see the elements in the list.
    "
            end
        end
    end
    
    document plist
        Prints std::list<T> information.
        Syntax: plist <list> <T> <idx>: Prints list size, if T defined all elements or just element at idx
        Examples:
        plist l - prints list size and definition
        plist l int - prints all elements and list size
        plist l int 2 - prints the third element in the list (if exists) and list size
    end
    
    define plist_member
        if $argc == 0
            help plist_member
        else
            set $head = &$arg0._M_impl._M_node
            set $current = $arg0._M_impl._M_node._M_next
            set $size = 0
            while $current != $head
                if $argc == 3
                    printf "elem[%u]: ", $size
                    p (*($arg1*)($current + 1)).$arg2
                end
                if $argc == 4
                    if $size == $arg3
                        printf "elem[%u]: ", $size
                        p (*($arg1*)($current + 1)).$arg2
                    end
                end
                set $current = $current._M_next
                set $size++
            end
            printf "List size = %u 
    ", $size
            if $argc == 1
                printf "List "
                whatis $arg0
                printf "Use plist_member <variable_name> <element_type> <member> to see the elements in the list.
    "
            end
        end
    end
    
    document plist_member
        Prints std::list<T> information.
        Syntax: plist <list> <T> <idx>: Prints list size, if T defined all elements or just element at idx
        Examples:
        plist_member l int member - prints all elements and list size
        plist_member l int member 2 - prints the third element in the list (if exists) and list size
    end
    
    
    #
    # std::map and std::multimap
    #
    
    define pmap
        if $argc == 0
            help pmap
        else
            set $tree = $arg0
            set $i = 0
            set $node = $tree._M_t._M_impl._M_header._M_left
            set $end = $tree._M_t._M_impl._M_header
            set $tree_size = $tree._M_t._M_impl._M_node_count
            if $argc == 1
                printf "Map "
                whatis $tree
                printf "Use pmap <variable_name> <left_element_type> <right_element_type> to see the elements in the map.
    "
            end
            if $argc == 3
                while $i < $tree_size
                    set $value = (void *)($node + 1)
                    printf "elem[%u].left: ", $i
                    p *($arg1*)$value
                    set $value = $value + sizeof($arg1)
                    printf "elem[%u].right: ", $i
                    p *($arg2*)$value
                    if $node._M_right != 0
                        set $node = $node._M_right
                        while $node._M_left != 0
                            set $node = $node._M_left
                        end
                    else
                        set $tmp_node = $node._M_parent
                        while $node == $tmp_node._M_right
                            set $node = $tmp_node
                            set $tmp_node = $tmp_node._M_parent
                        end
                        if $node._M_right != $tmp_node
                            set $node = $tmp_node
                        end
                    end
                    set $i++
                end
            end
            if $argc == 4
                set $idx = $arg3
                set $ElementsFound = 0
                while $i < $tree_size
                    set $value = (void *)($node + 1)
                    if *($arg1*)$value == $idx
                        printf "elem[%u].left: ", $i
                        p *($arg1*)$value
                        set $value = $value + sizeof($arg1)
                        printf "elem[%u].right: ", $i
                        p *($arg2*)$value
                        set $ElementsFound++
                    end
                    if $node._M_right != 0
                        set $node = $node._M_right
                        while $node._M_left != 0
                            set $node = $node._M_left
                        end
                    else
                        set $tmp_node = $node._M_parent
                        while $node == $tmp_node._M_right
                            set $node = $tmp_node
                            set $tmp_node = $tmp_node._M_parent
                        end
                        if $node._M_right != $tmp_node
                            set $node = $tmp_node
                        end
                    end
                    set $i++
                end
                printf "Number of elements found = %u
    ", $ElementsFound
            end
            if $argc == 5
                set $idx1 = $arg3
                set $idx2 = $arg4
                set $ElementsFound = 0
                while $i < $tree_size
                    set $value = (void *)($node + 1)
                    set $valueLeft = *($arg1*)$value
                    set $valueRight = *($arg2*)($value + sizeof($arg1))
                    if $valueLeft == $idx1 && $valueRight == $idx2
                        printf "elem[%u].left: ", $i
                        p $valueLeft
                        printf "elem[%u].right: ", $i
                        p $valueRight
                        set $ElementsFound++
                    end
                    if $node._M_right != 0
                        set $node = $node._M_right
                        while $node._M_left != 0
                            set $node = $node._M_left
                        end
                    else
                        set $tmp_node = $node._M_parent
                        while $node == $tmp_node._M_right
                            set $node = $tmp_node
                            set $tmp_node = $tmp_node._M_parent
                        end
                        if $node._M_right != $tmp_node
                            set $node = $tmp_node
                        end
                    end
                    set $i++
                end
                printf "Number of elements found = %u
    ", $ElementsFound
            end
            printf "Map size = %u
    ", $tree_size
        end
    end
    
    document pmap
        Prints std::map<TLeft and TRight> or std::multimap<TLeft and TRight> information. Works for std::multimap as well.
        Syntax: pmap <map> <TtypeLeft> <TypeRight> <valLeft> <valRight>: Prints map size, if T defined all elements or just element(s) with val(s)
        Examples:
        pmap m - prints map size and definition
        pmap m int int - prints all elements and map size
        pmap m int int 20 - prints the element(s) with left-value = 20 (if any) and map size
        pmap m int int 20 200 - prints the element(s) with left-value = 20 and right-value = 200 (if any) and map size
    end
    
    
    define pmap_member
        if $argc == 0
            help pmap_member
        else
            set $tree = $arg0
            set $i = 0
            set $node = $tree._M_t._M_impl._M_header._M_left
            set $end = $tree._M_t._M_impl._M_header
            set $tree_size = $tree._M_t._M_impl._M_node_count
            if $argc == 1
                printf "Map "
                whatis $tree
                printf "Use pmap <variable_name> <left_element_type> <right_element_type> to see the elements in the map.
    "
            end
            if $argc == 5
                while $i < $tree_size
                    set $value = (void *)($node + 1)
                    printf "elem[%u].left: ", $i
                    p (*($arg1*)$value).$arg2
                    set $value = $value + sizeof($arg1)
                    printf "elem[%u].right: ", $i
                    p (*($arg3*)$value).$arg4
                    if $node._M_right != 0
                        set $node = $node._M_right
                        while $node._M_left != 0
                            set $node = $node._M_left
                        end
                    else
                        set $tmp_node = $node._M_parent
                        while $node == $tmp_node._M_right
                            set $node = $tmp_node
                            set $tmp_node = $tmp_node._M_parent
                        end
                        if $node._M_right != $tmp_node
                            set $node = $tmp_node
                        end
                    end
                    set $i++
                end
            end
            if $argc == 6
                set $idx = $arg5
                set $ElementsFound = 0
                while $i < $tree_size
                    set $value = (void *)($node + 1)
                    if *($arg1*)$value == $idx
                        printf "elem[%u].left: ", $i
                        p (*($arg1*)$value).$arg2
                        set $value = $value + sizeof($arg1)
                        printf "elem[%u].right: ", $i
                        p (*($arg3*)$value).$arg4
                        set $ElementsFound++
                    end
                    if $node._M_right != 0
                        set $node = $node._M_right
                        while $node._M_left != 0
                            set $node = $node._M_left
                        end
                    else
                        set $tmp_node = $node._M_parent
                        while $node == $tmp_node._M_right
                            set $node = $tmp_node
                            set $tmp_node = $tmp_node._M_parent
                        end
                        if $node._M_right != $tmp_node
                            set $node = $tmp_node
                        end
                    end
                    set $i++
                end
                printf "Number of elements found = %u
    ", $ElementsFound
            end
            printf "Map size = %u
    ", $tree_size
        end
    end
    
    document pmap_member
        Prints std::map<TLeft and TRight> or std::multimap<TLeft and TRight> information. Works for std::multimap as well.
        Syntax: pmap <map> <TtypeLeft> <TypeRight> <valLeft> <valRight>: Prints map size, if T defined all elements or just element(s) with val(s)
        Examples:
        pmap_member m class1 member1 class2 member2 - prints class1.member1 : class2.member2
        pmap_member m class1 member1 class2 member2 lvalue - prints class1.member1 : class2.member2 where class1 == lvalue
    end
    
    
    #
    # std::set and std::multiset
    #
    
    define pset
        if $argc == 0
            help pset
        else
            set $tree = $arg0
            set $i = 0
            set $node = $tree._M_t._M_impl._M_header._M_left
            set $end = $tree._M_t._M_impl._M_header
            set $tree_size = $tree._M_t._M_impl._M_node_count
            if $argc == 1
                printf "Set "
                whatis $tree
                printf "Use pset <variable_name> <element_type> to see the elements in the set.
    "
            end
            if $argc == 2
                while $i < $tree_size
                    set $value = (void *)($node + 1)
                    printf "elem[%u]: ", $i
                    p *($arg1*)$value
                    if $node._M_right != 0
                        set $node = $node._M_right
                        while $node._M_left != 0
                            set $node = $node._M_left
                        end
                    else
                        set $tmp_node = $node._M_parent
                        while $node == $tmp_node._M_right
                            set $node = $tmp_node
                            set $tmp_node = $tmp_node._M_parent
                        end
                        if $node._M_right != $tmp_node
                            set $node = $tmp_node
                        end
                    end
                    set $i++
                end
            end
            if $argc == 3
                set $idx = $arg2
                set $ElementsFound = 0
                while $i < $tree_size
                    set $value = (void *)($node + 1)
                    if *($arg1*)$value == $idx
                        printf "elem[%u]: ", $i
                        p *($arg1*)$value
                        set $ElementsFound++
                    end
                    if $node._M_right != 0
                        set $node = $node._M_right
                        while $node._M_left != 0
                            set $node = $node._M_left
                        end
                    else
                        set $tmp_node = $node._M_parent
                        while $node == $tmp_node._M_right
                            set $node = $tmp_node
                            set $tmp_node = $tmp_node._M_parent
                        end
                        if $node._M_right != $tmp_node
                            set $node = $tmp_node
                        end
                    end
                    set $i++
                end
                printf "Number of elements found = %u
    ", $ElementsFound
            end
            printf "Set size = %u
    ", $tree_size
        end
    end
    
    document pset
        Prints std::set<T> or std::multiset<T> information. Works for std::multiset as well.
        Syntax: pset <set> <T> <val>: Prints set size, if T defined all elements or just element(s) having val
        Examples:
        pset s - prints set size and definition
        pset s int - prints all elements and the size of s
        pset s int 20 - prints the element(s) with value = 20 (if any) and the size of s
    end
    
    
    
    #
    # std::dequeue
    #
    
    define pdequeue
        if $argc == 0
            help pdequeue
        else
            set $size = 0
            set $start_cur = $arg0._M_impl._M_start._M_cur
            set $start_last = $arg0._M_impl._M_start._M_last
            set $start_stop = $start_last
            while $start_cur != $start_stop
                p *$start_cur
                set $start_cur++
                set $size++
            end
            set $finish_first = $arg0._M_impl._M_finish._M_first
            set $finish_cur = $arg0._M_impl._M_finish._M_cur
            set $finish_last = $arg0._M_impl._M_finish._M_last
            if $finish_cur < $finish_last
                set $finish_stop = $finish_cur
            else
                set $finish_stop = $finish_last
            end
            while $finish_first != $finish_stop
                p *$finish_first
                set $finish_first++
                set $size++
            end
            printf "Dequeue size = %u
    ", $size
        end
    end
    
    document pdequeue
        Prints std::dequeue<T> information.
        Syntax: pdequeue <dequeue>: Prints dequeue size, if T defined all elements
        Deque elements are listed "left to right" (left-most stands for front and right-most stands for back)
        Example:
        pdequeue d - prints all elements and size of d
    end
    
    
    
    #
    # std::stack
    #
    
    define pstack
        if $argc == 0
            help pstack
        else
            set $start_cur = $arg0.c._M_impl._M_start._M_cur
            set $finish_cur = $arg0.c._M_impl._M_finish._M_cur
            set $size = $finish_cur - $start_cur
            set $i = $size - 1
            while $i >= 0
                p *($start_cur + $i)
                set $i--
            end
            printf "Stack size = %u
    ", $size
        end
    end
    
    document pstack
        Prints std::stack<T> information.
        Syntax: pstack <stack>: Prints all elements and size of the stack
        Stack elements are listed "top to buttom" (top-most element is the first to come on pop)
        Example:
        pstack s - prints all elements and the size of s
    end
    
    
    
    #
    # std::queue
    #
    
    define pqueue
        if $argc == 0
            help pqueue
        else
            set $start_cur = $arg0.c._M_impl._M_start._M_cur
            set $finish_cur = $arg0.c._M_impl._M_finish._M_cur
            set $size = $finish_cur - $start_cur
            set $i = 0
            while $i < $size
                p *($start_cur + $i)
                set $i++
            end
            printf "Queue size = %u
    ", $size
        end
    end
    
    document pqueue
        Prints std::queue<T> information.
        Syntax: pqueue <queue>: Prints all elements and the size of the queue
        Queue elements are listed "top to bottom" (top-most element is the first to come on pop)
        Example:
        pqueue q - prints all elements and the size of q
    end
    
    
    
    #
    # std::priority_queue
    #
    
    define ppqueue
        if $argc == 0
            help ppqueue
        else
            set $size = $arg0.c._M_impl._M_finish - $arg0.c._M_impl._M_start
            set $capacity = $arg0.c._M_impl._M_end_of_storage - $arg0.c._M_impl._M_start
            set $i = $size - 1
            while $i >= 0
                p *($arg0.c._M_impl._M_start + $i)
                set $i--
            end
            printf "Priority queue size = %u
    ", $size
            printf "Priority queue capacity = %u
    ", $capacity
        end
    end
    
    document ppqueue
        Prints std::priority_queue<T> information.
        Syntax: ppqueue <priority_queue>: Prints all elements, size and capacity of the priority_queue
        Priority_queue elements are listed "top to buttom" (top-most element is the first to come on pop)
        Example:
        ppqueue pq - prints all elements, size and capacity of pq
    end
    
    
    
    #
    # std::bitset
    #
    
    define pbitset
        if $argc == 0
            help pbitset
        else
            p /t $arg0._M_w
        end
    end
    
    document pbitset
        Prints std::bitset<n> information.
        Syntax: pbitset <bitset>: Prints all bits in bitset
        Example:
        pbitset b - prints all bits in b
    end
    
    
    
    #
    # std::string
    #
    
    define pstring
        if $argc == 0
            help pstring
        else
            printf "String 			= "%s"
    ", $arg0._M_data()
            printf "String size/length 	= %u
    ", $arg0._M_rep()._M_length
            printf "String capacity 	= %u
    ", $arg0._M_rep()._M_capacity
            printf "String ref-count 	= %d
    ", $arg0._M_rep()._M_refcount
        end
    end
    
    document pstring
        Prints std::string information.
        Syntax: pstring <string>
        Example:
        pstring s - Prints content, size/length, capacity and ref-count of string s
    end 
    
    #
    # std::wstring
    #
    
    define pwstring
        if $argc == 0
            help pwstring
        else
            call printf("WString 		= "%ls"
    ", $arg0._M_data())
            printf "WString size/length 	= %u
    ", $arg0._M_rep()._M_length
            printf "WString capacity 	= %u
    ", $arg0._M_rep()._M_capacity
            printf "WString ref-count 	= %d
    ", $arg0._M_rep()._M_refcount
        end
    end
    
    document pwstring
        Prints std::wstring information.
        Syntax: pwstring <wstring>
        Example:
        pwstring s - Prints content, size/length, capacity and ref-count of wstring s
    end 
    
    #
    # C++ related beautifiers (optional)
    #
    
    set print pretty on
    set print object on
    set print static-members on
    set print vtbl on
    set print demangle on
    set demangle-style gnu-v3
    set print sevenbit-strings off

    拷贝到vim的时候可能会因为前面的注释的#的原因,导致后边自动地缩进,造成代码很乱。这个可以通过vim的format来解决。拷贝完成后,按《Esc》退出insert模式,回到普通模式。然后按gg,可以回到第一行第一个字符。然后放大招"gg=G",这四个键可以把所有代码重新排一下,变得好看,整齐。按完之后,按Ctrl+f键翻页看看吧。此时代码应该已经和网页上显示的一毛一样了。

    2.比如现在的stl_views_1.0.3.gdb文件的路径是/tmp下,即/tmp/stl_views_1.0.3.gdb。此时先写一个c++测试文件。

      $ vim test2.cc

     1 #include<map>
     2 #include<string>
     3 #include<vector>
     4 
     5 using namespace std;
     6 int main()
     7 {
     8     vector<int> myVector;
     9     myVector.push_back(1);
    10     myVector.push_back(2);
    11     return 0;
    12 }

      $ g++  -o  test2  test2.cc  -g

    此时/tmp下应该有一个可运行的test2和一个stl_view_1.0.3.gdb文件。然后让我们启动gdb吧,为了显示直观一些,可以用cgdb来可视化代码。

      $ cgdb  test2

     然后输入source /tmp/stl_view_1.0.3.gdb来引入这个工具。

    ok,现在开始执行test2可运行文件。先在main()设置断点,然后next,next,next,然后print myVector就可以看到工具的效果了。

     

    此时可以看到,工具的效果就出来了

    打印map的话,pmap ;打印vector的,pvector;

    可以查看帮助,source进来以后,用help  pvector来看使用帮助。

  • 相关阅读:
    文件处理
    集合 字符编码
    3-11作业
    win 10 在vs2017下对mpi的安装以及认识
    java中二维数组的排序
    java中Arrays的用法
    java中随机二维数组中寻找最大值并输出坐标
    用java打印图形
    面向对象object与constructor
    for each in for in 与for of
  • 原文地址:https://www.cnblogs.com/lukairui/p/6862130.html
Copyright © 2011-2022 走看看