zoukankan      html  css  js  c++  java
  • Debugging with GDB v10.1中文翻译-第一章:一个GDB 会话样例

    第一章:一个GDB 会话样例(未校正)

    你可以在闲暇时读完这本手册来了解所有关于gdb的内容。不过,仅需几个命令就足以开始使用调试器了。本章介绍了这些命令。
    在这个示例会话中,我们强调用户这样输入:input,以使它更容易从周围的输出中突出出来。
    gnu m4(一个通用宏处理器)的一个初步版本表现出以下缺陷:有时,当我们改变它的缺省引用字符串时,用于在另一个宏定义中捕获一个宏定义的命令停止工作。在下面简短的m4会话中,我们定义了一个扩展到0000的宏foo然后,我们使用m4内置defnbar定义为相同的东西。但是,当我们将开始引用字符串更改为 并将结束引用字符串更改为 时,相同的过程无法定义新的同义词baz:

    baz:
    $ cd gnu/m4
    $ ./m4
    define(foo,0000)
    foo
    0000
    define(bar,defn(‘foo’))
    bar
    0000
    changequote(<QUOTE>,<UNQUOTE>)
    define(baz,defn(<QUOTE>foo<UNQUOTE>))
    baz
    Ctrl-d
    m4: End of input: 0: fatal error: EOF in string
    

    让我们来尝试看看发生了什么。

    $ gdb m4
    gdb is free software and you are welcome to distribute copies
    of it under certain conditions; type "show copying" to see
    the conditions.
    There is absolutely no warranty for gdb; type "show warranty"
    for details.
    gdb 10.1, Copyright 1999 Free Software Foundation, Inc...
    (gdb)
    

    gdb只读取足够的符号数据,以便在需要时知道在哪里可以找到剩余的符号数据;因此,第一个提示会很快出现。我们现在告诉gdb使用比通常更窄的显示宽度,这样例子就适合本手册。

    (gdb) set width 70
    

    我们需要看看m4内置的changequote是如何工作的。看了源代码之后,我们知道相关的子程序是m4_changequote,所以我们用gdb break命令在那里设置了一个断点。

    (gdb) break m4 changequote
    Breakpoint 1 at 0x62f4: file builtin.c, line 879.
    

    使用run命令,我们开始在gdb控制下运行M4;只要没有运行到m4_changequote子程序,程序就照常运行:

    (gdb) run
    Starting program: /work/Editorial/gdb/gnu/m4/m4
    define(foo,0000)
    
    foo
    0000
    

    为了触发断点,我们调用changequote。gdb挂起m4的执行,在程序停止的地方显示上下文信息。

    changequote(<QUOTE>,<UNQUOTE>)
    Breakpoint 1, m4_changequote (argc=3, argv=0x33c70)
    at builtin.c:879
    879 if (bad_argc(TOKEN_DATA_TEXT(argv[0]),argc,1,3))
    

    现在我们使用命令n (next) 将程序执行到当前函数的下一行。

    (gdb) n
    882 set_quotes((argc >= 2) ? TOKEN_DATA_TEXT(argv[1])
    : nil,
    

    set_quotes看起来是一个很有前途的子程序。我们可以通过使用命令s(step) 而不是next来进入这个子函数。step转到任何子程序中要执行的下一行,因此它会进入set_quotes函数。

    (gdb) s
    set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
    at input.c:530
    530 if (lquote != def_lquote)
    

    展示的m4现在暂停的子函数(及其参数)的显示称为堆栈帧显示。它显示了堆栈的摘要。我们可以使用backtrace命令(也可以拼写为bt),来查看我们在整个堆栈中的位置:backtrace命令为每个活动的子函数显示一个堆栈帧。

    (gdb) bt
    #0 set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
    at input.c:530
    #1 0x6344 in m4_changequote (argc=3, argv=0x33c70)
    at builtin.c:882
    #2 0x8174 in expand_macro (sym=0x33320) at macro.c:242
    #3 0x7a88 in expand_token (obs=0x0, t=209696, td=0xf7fffa30)
    at macro.c:71
    #4 0x79dc in expand_input () at macro.c:40
    #5 0x2930 in main (argc=0, argv=0xf7fffb20) at m4.c:195
    

    我们再看几行,看看会发生什么。前两次,我们可以用' s ';接下来的两次,我们使用n来避免陷入xstrdup子函数。

    (gdb) s
    0x3b5c 532 if (rquote != def_rquote)
    (gdb) s
    0x3b80 535 lquote = (lq == nil || *lq == ’’) ? 
    def_lquote : xstrdup(lq);
    (gdb) n
    536 rquote = (rq == nil || *rq == ’’) ? def_rquote
    : xstrdup(rq);
    (gdb) n
    538 len_lquote = strlen(rquote);
    

    显示的最后一行看起来有点奇怪;我们可以检查变量lquoterquote,看看它们是否是我们指定的新的左引号和右引号。我们使用命令p(print)来查看它们的值。

    (gdb) p lquote
    $1 = 0x35d40 "<QUOTE>"
    (gdb) p rquote
    $2 = 0x35d50 "<UNQUOTE>"
    

    lquoterquote确实是新的左引号和右引号。为了查看一些内容,我们可以用l(list) 命令在当前行周围显示10行源代码。

    (gdb) l
    533 xfree(rquote);
    534
    535 lquote = (lq == nil || *lq == ’’) ? def_lquote
    : xstrdup (lq);
    536 rquote = (rq == nil || *rq == ’’) ? def_rquote
    : xstrdup (rq);
    537
    538 len_lquote = strlen(rquote);
    539 len_rquote = strlen(lquote);
    540 }
    541
    542 void
    

    让我们跳过设置len_lquotelen_rquote的两行,然后检查这些变量的值。

    (gdb) n
    539 len_rquote = strlen(lquote);
    (gdb) n
    540 }
    (gdb) p len lquote
    $3 = 9
    (gdb) p len rquote
    $4 = 7
    

    假设len_lquotelen_rquote分别是lquoterquote的长度,这显然是错误的。我们可以使用p命令将它们设置为更好的值,因为它可以打印任何表达式的值——并且该表达式可以包括子函数调用和赋值。

    (gdb) p len lquote=strlen(lquote)
    $5 = 7
    (gdb) p len rquote=strlen(rquote)
    $6 = 9
    

    这是否足以解决m4内置defn使用新引用的问题?我们可以允许m4继续使用c(continue) 命令执行,然后尝试最初导致问题的示例:

    (gdb) c
    Continuing.
    define(baz,defn(<QUOTE>foo<UNQUOTE>))
    baz
    0000
    

    成功!新引用现在和默认引用一样有效。问题似乎只是定义了错误长度的两个错别字。我们允许m4退出,给它一个EOF作为输入:

    Ctrl-d
    Program exited normally.
    

    消息“Program exited normally. 。来自gdb它表示m4已经完成执行。我们可以用GDB退出命令结束我们的GDB会话。

    (gdb) quit
    
  • 相关阅读:
    在Postman用post方式请求webapi
    C#控制台为输出内容设置背景色和字体颜色
    不卡界面,实现文件上传
    编译后的dll,xml,pdb分别是什么内容,各有什么用处?
    C#的dynamic解析xml
    Oracle中的正则表达式
    oracle中 connect by 递归查询用法
    oracle中 listagg() WITHIN GROUP () 行转列函数的使用
    oracle中dualde使用
    MYSQL基本命令
  • 原文地址:https://www.cnblogs.com/Songhe/p/14507143.html
Copyright © 2011-2022 走看看