881shell白带多是怎么回事事?

& 用 GDB 调试程序
用 GDB 调试程序
用 调试程序
GDB 是 开源组织发布的一个强大的 下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像 、 等 的调试,但如果你是在 平台下做软件,你会发现 这个调试工具有比 、 的图形化调试器更强大的功能。所谓 “ 寸有所长,尺有所短 ” 就是这个道理。
一般来说, 主要帮忙你完成下面四个方面的功能:
1 、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2 、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3 、当程序被停住时,可以检查此时你的程序中所发生的事。
4 、动态的改变你程序的执行环境。
从上面看来, 和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现 这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。
一个调试示例
——————
编译生成执行文件:( 下)
使用 调试:
hchen/test& gdb tst
&---------- 启动
&-------------------- l 命令相当于 ,从第一行开始例出原码。
&-------------------- 直接回车表示,重复上一次命令
(gdb) break 16
&-------------------- 设置断点,在源程序第 行处。
(gdb) break func
&-------------------- 设置断点,在函数 入口处。
(gdb) info break
&-------------------- 查看断点信息。
&--------------------- 运行程序, 命令简写
Breakpoint 1, main () at tst.c:17
&---------- 在断点处停住。
&--------------------- 单条语句执行, 命令简写。
&--------------------- 继续运行程序, 命令简写。
result[1-100] = 5050
&---------- 程序输出。
&--------------------- 打印变量 的值, 命令简写。
&--------------------- 查看函数堆栈。
(gdb) finish
&--------------------- 退出函数。
&--------------------- 继续运行。
result[1-250] = 31375
&---------- 程序输出。
Program exited with code 027. &-------- 程序退出,调试结束。
&--------------------- 退出 。
好了,有了以上的感性认识,还是让我们来系统地认识一下 吧。
一般来说 主要调试的是 的程序。要调试 的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器( )的 参数可以做到这一点。如:
如果没有 ,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。当你用 把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用 来调试他。
启动 的方法有以下几种:
program 也就是你的执行文件,一般在当然目录下。
用 同时调试一个运行程序和 文件, 是程序非法执行后 后产生的文件。
如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程 。 会自动 上去,并调试他。 应该在 环境变量中搜索得到。
GDB 启动时,可以加上一些 的启动开关,详细的开关可以用 查看。我在下面只例举一些比较常用的参数:
从指定文件中读取符号表。
从指定文件中读取符号表信息,并把他用在可执行文件中。
调试时 的 文件。
加入一个源文件的搜索路径。默认搜索路径是环境变量中 所定义的路径。
GDB 的命令概貌
———————
启动 后,就你被带入 的调试环境中,就可以使用 的命令开始调试程序了, 的命令可以使用 命令来查看,如下所示:
gdb 的命令很多, 把之分成许多个种类。 命令只是例出 的命令种类,如果要看种类中的命令,可以使用 命令,如: ,查看设置断点的所有命令。也可以直接 来查看命令的帮助。
gdb 中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,命令的前几个字符应该要标志着一个唯一的命令,在 下,你可以敲击两次 键来补齐命令的全称,如果有重复的,那么 会把其例出来。
示例一:在进入函数 时,设置一个断点。可以敲入 ,或是直接就是
示例二:敲入 按两次 键,你会看到所有 打头的命令:
示例三:只记得函数的前缀,可以这样:
(gdb) b make_ & 按 键
(再按下一次 键,你会看到 )
GDB 把所有 开头的函数全部例出来给你查看。
示例四:调试 的程序时,有可以函数名一样。如:
你可以查看到 中的所有的重载函数及参数。(注: 和 “ 按两次 键 ” 是一个意思)
要退出 时,只用发 或命令简称 就行了。
3、中运行 的 程序
————————————
在 环境中,你可以执行 的 的命令,使用 的 命令来完成:
调用 的 来执行 ,环境变量 中定义的 的 将会被用来执行 ,如果 没有定义,那就使用 的标准 : 。(在 中使用 或 )
还有一个 命令是 :
可以在 中执行 命令来重新 自己的程序。这个命令等价于 “ ” 。
在 中运行程序
————————
当以 方式启动 后, 会在 路径和当前目录中搜索 的源文件。如要确认 是否读到源文件,可使用 或 命令,看看 是否能列出源代码。
在 中,运行程序使用 或是 命令。程序的运行,你有可能需要设置下面四方面的事。
1 、程序运行参数。
set args 可指定运行时参数。(如: )
show args 命令可以查看设置好的运行参数。
2 、运行环境。
path &dir& 可设定程序的运行路径。
show paths 查看程序的运行路径。
set environment varname [=value] 设置环境变量。如:
show environment [varname] 查看环境变量。
3 、工作目录。
cd &dir& 相当于 的 命令。
pwd 显示当前的所在目录。
4 、程序的输入输出。
info terminal 显示你程序用到的终端的模式。
使用重定向控制程序输出。如:
tty 命令可以指写输入输出的终端设备。如:
4、调试已运行的程序
————————
两种方法:
1 、在 下用 查看正在运行的程序的 (进程 ),然后用 格式挂接正在运行的程序。
2 、先用 关联上源代码,并进行 ,在 中用 命令来挂接进程的 。并用 来取消挂接的进程。
暂停 恢复程序运行
—————————
调试程序中,暂停程序运行是必须的, 可以方便地暂停程序的运行。你可以设置程序的在哪行停住,在什么条件下停住,在收到什么信号时停往等等。以便于你查看运行时的变量,以及运行时的流程。
当进程被 停住时,你可以使用 来查看程序的是否在运行,进程号,被暂停的原因。
在 中,我们可以有以下几种暂停方式:断点( )、观察点( )、捕捉点( )、信号( )、线程停止( )。如果要恢复程序运行,可以使用 或是 命令。
一、设置断点( BreakPoint )
我们用 命令来设置断点。正面有几点设置断点的方法:
在进入指定函数时停住。 中可以使用 或 格式来指定函数名。
在指定行号停住。
在当前行号的前面或后面的 行停住。 为自然数。
在源文件 的 行处停住。
在源文件 的 函数的入口处停住。
在程序运行的内存地址处停住。
break 命令没有参数时,表示在下一条指令处停住。
... 可以是上述的参数, 表示条件,在条件成立时停住。比如在循环境体中,可以设置 ,表示当 为 时停住程序。
查看断点时,可使用 命令,如下所示:(注: 表示断点号)
二、设置观察点( WatchPoint )
观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点:
为表达式(变量) 设置一个观察点。一量表达式值有变化时,马上停住程序。
当表达式(变量) 被读时,停住程序。
当表达式(变量)的值被读或被写时,停住程序。
列出当前所设置了的所有观察点。
三、设置捕捉点( CatchPoint )
你可设置捕捉点来补捉程序运行时的一些事件。如:载入共享库(动态链接库)或是 的异常。设置捕捉点的格式为:
当 发生时,停住程序。 可以是下面的内容:
1 、 一个 抛出的异常。( 为关键字)
2 、 一个 捕捉到的异常。( 为关键字)
3 、 调用系统调用 时。( 为关键字,目前此功能只在 下有用)
4 、 调用系统调用 时。( 为关键字,目前此功能只在 下有用)
5 、 调用系统调用 时。( 为关键字,目前此功能只在 下有用)
6 、 或 载入共享库(动态链接库)时。( 为关键字,目前此功能只在 下有用)
7 、 或 卸载共享库(动态链接库)时。( 为关键字,目前此功能只在 下有用)
只设置一次捕捉点,当程序停住以后,应点被自动删除。
四、维护停止点
上面说了如何设置程序的停止点, 中的停止点也就是上述的三类。在 中,如果你觉得已定义好的停止点没有用了,你可以使用 、 、 、 这几个命令来进行维护。
清除所有的已定义的停止点。
清除所有设置在函数上的停止点。
清除所有设置在指定行上的停止点。
删除指定的断点, 为断点号。如果不指定断点号,则表示删除所有的断点。 表示断点号的范围(如: )。其简写命令为 。
比删除更好的一种方法是 停止点, 了的停止点, 不会删除,当你还需要时, 即可,就好像回收站一样。
disable 所指定的停止点, 为停止点号。如果什么都不指定,表示 所有的停止点。简写命令是
enable 所指定的停止点, 为停止点号。
enable 所指定的停止点一次,当程序停止后,该停止点马上被 自动 。
enable 所指定的停止点一次,当程序停止后,该停止点马上被 自动删除。
五、停止条件维护
前面在说到设置断点时,我们提到过可以设置一个条件,当条件成立时,程序自动停止,这是一个非常强大的功能,这里,我想专门说说这个条件的相关维护命令。一般来说,为断点设置一个条件,我们使用 关键词,后面跟其断点条件。并且,条件设置好后,我们可以用 命令来修改断点的条件。(只有 和 命令支持 , 目前暂不支持 )
修改断点号为 的停止条件为 。
清除断点号为 的停止条件。
还有一个比较特殊的维护命令 ,你可以指定程序运行时,忽略停止条件几次。
表示忽略断点号为 的停止条件 次。
六、为停止点设定运行命令
我们可以使用 提供的 命令来设置停止点的运行命令。也就是说,当运行的程序在被停止住时,我们可以让其自动运行一些别的命令,这很有利行自动化调试。对基于 的自动化调试是一个强大的支持。
为断点号 指写一个命令列表。当程序被该断点停住时, 会依次运行命令列表中的命令。
断点设置在函数 中,断点条件是 ,如果程序被断住后,也就是,一旦 的值在 函数中大于 , 会自动打印出 的值,并继续运行程序。
如果你要清除断点上的命令序列,那么只要简单的执行一下 命令,并直接在打个 就行了。
七、断点菜单
在 中,可能会重复出现同一个名字的函数若干次(函数重载),在这种情况下, 不能告诉 要停在哪个函数的入口。当然,你可以使用 也就是把函数的参数类型告诉 ,以指定一个函数。否则的话, 会给你列出一个断点菜单供你选择你所需要的断点。你只要输入你菜单列表中的编号就可以了。如:
可见, 列出了所有 的重载函数,你可以选一下列表编号就行了。 表示放弃设置断点, 表示所有函数都设置断点。
八、恢复程序运行和单步调试
当程序被停住了,你可以用 命令恢复程序的运行直到程序结束,或下一个断点到来。也可以使用 或 命令单步跟踪程序。
恢复程序运行,直到程序结束,或是下一个断点到来。 表示忽略其后的断点次数。 , , 三个命令都是一样的意思。
单步跟踪,如果有函数调用,他会进入该函数。进入函数的前提是,此函数被编译有 信息。很像 等工具中的 。后面可以加 也可以不加,不加表示一条条地执行,加表示执行后面的 条指令,然后再停住。
同样单步跟踪,如果有函数调用,他不会进入该函数。很像 等工具中的 。后面可以加 也可以不加,不加表示一条条地执行,加表示执行后面的 条指令,然后再停住。
打开 模式,于是,在进行单步跟踪时,程序不会因为没有 信息而不停住。这个参数有很利于查看机器码。
关闭 模式。
运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息。
当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
单步跟踪一条机器指令!一条程序代码有可能由数条机器指令完成, 和 可以单步执行机器指令。与之一样有相同功能的命令是 “ ” ,当运行完这个命令后,单步跟踪会在打出程序代码的同时打出机器指令(也就是汇编代码)
九、信号( Signals )
信号是一种软中断,是一种处理异步事件的方法。一般来说,操作系统都支持许多信号。尤其是 ,比较重要应用程序一般都会处理信号。 定义了许多信号,比如 表示中断字符信号,也就是 的信号, 表示硬件故障的信号; 表示子进程状态改变信号; 表示终止程序运行的信号,等等。信号量编程是 下非常重要的一种技术。
GDB 有能力在你调试程序的时候处理任何一种信号,你可以告诉 需要处理哪一种信号。你可以要求 收到你所指定的信号时,马上停住正在运行的程序,以供你进行调试。你可以用 的 命令来完成这一功能。
在 中定义一个信号处理。信号 可以以 开头或不以 开头,可以用定义一个要处理信号的范围(如: ,表示处理从 信号到 的信号,其中包括 , , 三个信号),也可以使用关键字 来标明要处理所有的信号。一旦被调试的程序接收到信号,运行程序马上会被 停住,以供调试。其 可以是以下几种关键字的一个或多个。
当被调试的程序收到信号时, 不会停住程序的运行,但会打出消息告诉你收到这种信号。
当被调试的程序收到信号时, 会停住你的程序。
当被调试的程序收到信号时, 会显示出一条信息。
当被调试的程序收到信号时, 不会告诉你收到信号的信息。
当被调试的程序收到信号时, 不处理信号。这表示, 会把这个信号交给被调试程序会处理。
当被调试的程序收到信号时, 不会让被调试程序来处理这个信号。
查看有哪些信号在被 检测中。
十、线程( Thread Stops )
如果你程序是多线程的话,你可以定义你的断点是否在所有的线程上,或是在某个特定的线程。 很容易帮你完成这一工作。
linespec 指定了断点设置在的源程序的行号。 指定了线程的 ,注意,这个 是 分配的,你可以通过 “ ” 命令来查看正在运行程序中的线程信息。如果你不指定 则表示你的断点设在所有线程上面。你还可以为某线程指定断点条件。如:
当你的程序被 停住时,所有的运行线程都会被停住。这方便你你查看运行程序的总体情况。而在你恢复程序运行时,所有的线程也会被恢复运行。那怕是主进程在被单步调试时。
查看栈信息
—————
当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入 “ 栈 ” ( )中。你可以用 命令来查看当前的栈中的信息。
下面是一些查看函数调用栈信息的 命令:
打印当前的函数调用栈的所有信息。如:
从上可以看出函数的调用栈信息:
n 是一个正整数,表示只打印栈顶上 层的栈信息。
-n 表一个负整数,表示只打印栈底下 层的栈信息。
如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。
n 是一个从 开始的整数,是栈中的层编号。比如: ,表示栈顶, ,表示栈的第二层。
表示向栈的上面移动 层,可以不打 ,表示向上移动一层。
表示向栈的下面移动 层,可以不打 ,表示向下移动一层。
上面的命令,都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命令:
select-frame &n& 对应于 命令。
up-silently &n& 对应于 命令。
down-silently &n& 对应于 命令。
查看当前栈层的信息,你可以用以下 命令:
会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。
这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。如:
打印出当前函数的参数名及其值。
打印出当前函数中所有局部变量及其值。
打印出当前的函数中的异常处理信息。
5、查看源程序
一、显示源代码
GDB 可以打印出所调试程序的源代码,当然,在程序编译时一定要加上 的参数,把源程序信息编译到执行文件中。不然就看不到源程序了。当程序停下来以后, 会报告程序停在了那个文件的第几行上。你可以用 命令来打印程序的源代码。还是来看一看查看源代码的 命令吧。
显示程序第 行的周围的源程序。
显示函数名为 的函数的源程序。
显示当前行后面的源程序。
显示当前行前面的源程序。
一般是打印当前行的上 行和下 行,如果显示函数是是上 行下 行,默认是 行,当然,你也可以定制显示的范围,使用下面命令可以设置一次显示源程序的行数。
设置一次显示源代码的行数。
查看当前 的设置。
list 命令还有下面的用法:
显示从 行到 行之间的源代码。
显示从当前行到 行之间的源代码。
往后显示源代码。
一般来说在 后面可以跟以下这们的参数:
当前行号的正偏移量。
当前行号的负偏移量。
&filename:linenum&
哪个文件的哪一行。
&function&
&filename:function& 哪个文件中的哪个函数。
&*address&
程序运行时的语句在内存中的地址。
二、搜索源代码
不仅如此, 还提供了源代码搜索的命令:
向前面搜索。
全部搜索。
其中, 就是正则表达式,也主一个字符串的匹配模式,关于正则表达式,我就不在这里讲了,还请各位查看相关资料。
三、指定源文件的路径
某些时候,用 编译过后的执行程序中只是包括了源文件的名字,没有路径名。 提供了可以让你指定源文件的路径的命令,以便 进行搜索。
加一个源文件路径到当前路径的前面。如果你要指定多个路径, 下你可以使用 “ ” , 下你可以使用 “ ” 。
清除所有的自定义的源文件搜索路径信息。
显示定义了的源文件搜索路径。
四、源代码的内存
你可以使用 命令来查看源代码在内存中的地址。 后面可以跟 “ 行号 ” , “ 函数名 ” , “ 文件名 行号 ” , “ 文件名 函数名 ” ,这个命令会打印出所指定的源码在运行时的内存地址,如:
还有一个命令( )你可以查看源程序的当前执行时的机器码,这个命令会把目前内存中的指令 出来。如下面的示例表示查看函数 的汇编代码。
6、查看运行时数据
在你调试程序时,当程序被停住时,你可以使用 命令(简写命令为 ),或是同义命令 来查看当前程序的运行数据。 命令的格式是:
&expr& 是表达式,是你所调试的程序的语言的表达式( 可以调试多种编程语言), 是输出的格式,比如,如果要把表达式按 进制的格式输出,那么就是 。
一、表达式
print 和许多 的命令一样,可以接受一个表达式, 会根据当前的程序运行的数据来计算这个表达式,既然是表达式,那么就可以是当前程序运行中的 常量、变量、函数等内容。可惜的是 不能使用你在程序中所定义的宏。
表达式的语法应该是当前所调试的语言的语法,由于 是一种大众型的语言,所以,本文中的例子都是关于 的。(而关于用 调试其它语言的章节,我将在后面介绍)
在表达式中,有几种 所支持的操作符,它们可以用在任何一种语言中。
是一个和数组有关的操作符,在后面会有更详细的说明。
指定一个在文件或是一个函数中的变量。
表示一个指向内存地址 的类型为 的一个对象。
二、程序变量
在 中,你可以随时查看以下三种变量的值:
1 、全局变量(所有文件可见的)
2 、静态全局变量(当前文件可见的)
3 、局部变量(当前 可见的)
如果你的局部变量和全局变量发生冲突(也就是重名),一般情况下是局部变量会隐藏全局变量,也就是说,如果一个全局变量和一个函数中的局部变量同名时,如果当前停止点在函数中,用 显示出的变量的值会是函数中的局部变量的值。如果此时你想查看全局变量的值时,你可以使用 “ ” 操作符:
可以通过这种形式指定你所想查看的变量,是哪个文件中的或是哪个函数中的。例如,查看文件 中的全局变量 的值:
当然, “ ” 操作符会和 中的发生冲突, 能自动识别 “ ” 是否 的操作符,所以你不必担心在调试 程序时会出现异常。
另外,需要注意的是,如果你的程序编译时开启了优化选项,那么在用 调试被优化过的程序时,可能会发生某些变量不能访问,或是取值错误码的情况。这个是很正常的,因为优化程序会删改你的程序,整理你程序的语句顺序,剔除一些无意义的变量等,所以在 调试这种程序时,运行时的指令和你所编写指令就有不一样,也就会出现你所想象不到的结果。对付这种情况时,需要在编译程序时关闭编译优化。一般来说,几乎所有的编译器都支持编译优化的开关,例如, 的 编译器 ,你可以使用 “ ” 选项来解决这个问题。关于编译器的参数,还请查看编译器的使用说明文档。
有时候,你需要查看一段连续的内存空间的值。比如数组的一段,或是动态分配的数据的大小。你可以使用 的 “ ” 操作符, “ ” 的左边是第一个内存的地址的值, “ ” 的右边则你你想查看内存的长度。例如,你的程序中有这样的语句:
于是,在 调试过程中,你可以以如下命令显示出这个动态数组的取值:
@ 的左边是数组的首地址的值,也就是变量 所指向的内容,右边则是数据的长度,其保存在变量 中,其输出结果,大约是下面这个样子的:
如果是静态数组的话,可以直接用 数组名,就可以显示数组中所有数据的内容了。
四、输出格式
一般来说, 会根据变量的类型输出变量的值。但你也可以自定义 的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用 的数据显示格式:
按十六进制格式显示变量。
按十进制格式显示变量。
按十六进制格式显示无符号整型。
按八进制格式显示变量。
按二进制格式显示变量。
按十六进制格式显示变量。
按字符格式显示变量。
按浮点数格式显示变量。
五、查看内存
你可以使用 命令(简写是 )来查看内存地址中的值。 命令的语法如下所示:
n 、 、 是可选的参数。
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。
f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是 ,如果地十是指令地址,那么格式可以是 。
u 表示从当前地址往后请求的字节数,如果不指定的话, 默认是 个 。 参数可以用下面的字符来代替, 表示单字节, 表示双字节, 表示四字节, 表示八字节。当我们指定了字节长度后, 会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
&addr& 表示一个内存地址。
n/f/u 三个参数可以一起使用。例如:
命令: 表示,从内存地址 读取内容, 表示以双字节为一个单位, 表示三个单位, 表示按十六进制显示。
六、自动显示
你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的 命令是 。
expr 是一个表达式, 表示显示的格式, 表示内存地址,当你用 设定好了一个或多个表达式后,只要你的程序被停下来, 会自动显示你所设置的这些表达式的值。
格式 和 同样被 支持,一个非常有用的命令是:
$pc 是 的环境变量,表示着指令的地址, 则表示输出格式为机器指令码,也就是汇编。于是当程序停下后,就会出现源代码和机器指令码相对应的情形,这是一个很有意思的功能。
下面是一些和 相关的 命令:
删除自动显示, 意为所设置好了的自动显式的编号。如果要同时删除几个,编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如: )
disable 和 不删除自动显示的设置,而只是让其失效和恢复。
查看 设置的自动显示的信息。 会打出一张表格,向你报告当然调试中设置了多少个自动显示设置,其中包括,设置的编号,表达式,是否 。
七、设置显示选项
GDB 中关于显示的选项比较多,这里我只例举大多数常用的选项。
打开地址输出,当程序显示函数信息时, 会显出函数的参数地址。系统默认为打开的,如:
关闭函数的参数地址显示,如:
查看当前地址显示选项是否打开。
打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔。这个选项默认是关闭的。与之相关的两个命令如下,我就不再多说了。
这个选项主要是设置数组的,如果你的数组太大了,那么就可以指定一个 来指定数据显示的最大长度,当到达这个长度时, 就不再往下显示了。如果设置为 ,则表示不限制。
查看 的选项信息。
如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示。这个选项默认为 。
如果打开 这个选项,那么当 显示结构体时会比较漂亮。如:
关闭 这个选项, 显示结构体时会如下显示:
查看 是如何显示结构体的。
设置字符显示,是否按 “ ” 的格式显示,如果打开,则字符串或字符数据按 显示,如 “ ” 。
查看字符显示开关是否打开。
设置显示结构体时,是否显式其内的联合体数据。例如有以下数据结构:
当打开这个开关时,执行 命令后,会如下显示:
当关闭这个开关时,执行 命令后,会如下显示:
查看联合体数据的显示方式
在 中,如果一个对象指针指向其派生类,如果打开这个选项, 会自动按照虚方法调用的规则显示输出,如果关闭这个选项的话, 就不管虚函数表了。这个选项默认是 。
查看对象选项的设置。
这个选项表示,当显示一个 对象中的内容是,是否显示其中的静态数据成员。默认是 。
查看静态数据成员选项设置。
当此选项打开时, 将用比较规整的格式来显示虚函数表时。其默认是关闭的。
查看虚函数显示格式的选项。
八、历史记录
当你用 的 查看程序运行时的数据时,你每一个 都会被 记录下来。 会以 这样的方式为你每一个 命令编上号。于是,你可以使用这个编号访问以前的表达式,如 。这个功能所带来的好处是,如果你先前输入了一个比较长的表达式,如果你还想查看这个表达式的值,你可以使用历史记录来访问,省去了重复输入。
九、 GDB 环境变量
你可以在 的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。要定义一个 的变量很简单只需。使用 的 命令。 的环境变量和 一样,也是以 起头。如:
使用环境变量时, 会在你第一次使用时创建这个变量,而在以后的使用中,则直接对其賦值。环境变量没有类型,你可以给环境变量定义任一的类型。包括结构体和数组。
该命令查看当前所设置的所有的环境变量。
这是一个比较强大的功能,环境变量和程序变量的交互使用,将使得程序调试更为灵活便捷。例如:
于是,当你就不必, 地输入命令了。输入这样的命令后,只用敲回车,重复执行上一条语句,环境变量会自动累加,从而完成逐个输出的功能。
十、查看寄存器
要查看寄存器的值,很简单,可以使用如下命令:
查看寄存器的情况。(除了浮点寄存器)
查看所有寄存器的情况。(包括浮点寄存器)
查看所指定的寄存器的情况。
寄存器中放置了程序运行时的数据,比如程序当前运行的指令地址( ),程序的当前堆栈地址( )等等。你同样可以使用 命令来访问寄存器的情况,只需要在寄存器名字前加一个 符号就可以了。如: 。
改变程序的执行
———————
一旦使用 挂上被调试程序,当程序运行起来后,你可以根据自己的调试思路来动态地在 中更改当前被调试程序的运行线路或是其变量的值,这个强大的功能能够让你更好的调试你的程序,比如,你可以在程序的一次运行中走遍程序的所有分支。
一、修改变量值
修改被调试程序运行时的变量值,在 中很容易实现,使用 的 命令即可完成。如:
x=4 这个表达式是 的语法,意为把变量 的值修改为 ,如果你当前调试的语言是 ,那么你可以使用 的语法: 。
在某些时候,很有可能你的变量和 中的参数冲突,如:
因为, 是 的命令,所以,出现了 “ ” 的设置错误,此时,你可以使用 命令来告诉 , 不是你 的参数,而是程序的变量名,如:
另外,还可能有些情况, 并不报告这种错误,所以保险起见,在你改变程序变量取值时,最好都使用 格式的 命令。
二、跳转执行
一般来说,被调试程序会按照程序代码的运行顺序依次执行。 提供了乱序执行的功能,也就是说, 可以修改程序的执行顺序,可以让程序执行随意跳跃。这个功能可以由 的 命令来完:
指定下一条语句的运行点。 可以是文件的行号,可以是 格式,可以是 这种偏移量格式。表式着下一条运行语句从哪里开始。
这里的 是代码行的内存地址。
注意, 命令不会改变当前的程序栈中的内容,所以,当你从一个函数跳到另一个函数时,当函数运行完返回时进行弹栈操作时必然会发生错误,可能结果还是非常奇怪的,甚至于产生程序 。所以最好是同一个函数中进行跳转。
熟悉汇编的人都知道,程序运行时,有一个寄存器用于保存当前代码所在的内存地址。所以, 命令也就是改变了这个寄存器中的值。于是,你可以使用 “ ” 来更改跳转执行的地址。如:
三、产生信号量
使用 命令,可以产生一个信号量给被调试的程序。如:中断信号 。这非常方便于程序的调试,可以在程序运行的任意位置设置断点,并在该断点用 产生一个信号量,这种精确地在某处产生信号非常有利程序的调试。
语法是: , 的系统信号量通常从 到 。所以 取值也在这个范围。
single 命令和 的 命令不同,系统的 命令发信号给被调试程序时,是由 截获的,而 命令所发出一信号则是直接发给被调试程序的。
四、强制函数返回
如果你的调试断点在某个函数中,并还有语句没有执行完。你可以使用 命令强制函数忽略还没有执行的语句并返回。
使用 命令取消当前函数的执行,并立即返回,如果指定了 ,那么该表达式的值会被认作函数的返回值。
五、强制调用函数
表达式中可以一是函数,以此达到强制调用函数的目的。并显示函数的返回值,如果函数返回值是 ,那么就不显示。
另一个相似的命令也可以完成这一功能 —— , 后面可以跟表达式,所以也可以用他来调用函数, 和 的不同是,如果函数返回 , 则不显示, 则显示函数返回值,并把该值存入历史数据中。
在不同语言中使用
——————————
GDB 支持下列语言: 和 。一般说来, 会根据你所调试的程序来确定当然的调试语言,比如:发现文件名后缀为 “ ” 的, 会认为是 程序。文件名后缀为 “ ” 的, 会认为是 程序。而后缀是 “ ” 的, 会认为是 程序,还有,后缀为如果是 “ ” 的会认为是汇编语言。
也就是说, 会根据你所调试的程序的语言,来设置自己的语言环境,并让 的命令跟着语言环境的改变而改变。比如一些 命令需要用到表达式或变量时,这些表达式或变量的语法,完全是根据当前的语言环境而改变的。例如 中对指针的语法是 ,而在 中则是 。并且,如果你当前的程序是由几种不同语言一同编译成的,那到在调试过程中, 也能根据不同的语言自动地切换语言环境。这种跟着语言环境而改变的功能,真是体贴开发人员的一种设计。
下面是几个相关于 语言环境的命令:
查看当前的语言环境。如果 不能识为你所调试的编程语言,那么, 语言被认为是默认的环境。
查看当前函数的程序语言。
查看当前文件的程序语言。
如果 没有检测出当前的程序语言,那么你也可以手动设置当前的程序语言。使用 命令即可做到。
当 命令后什么也不跟的话,你可以查看 所支持的语言种类:
于是你可以在 后跟上被列出来的程序语言名,来设置当前的语言环境。
GDB 是一个强大的命令行调试工具。大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本。 下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优势在于,它们可以非常容易的集成在一起,使用几个简单的已有工具的命令,就可以做出一个非常强大的功能。
除非注明,本站文章均为: 原创,转载请注明本文地址:
查找问题解决方法时,你是不是经常发现同一篇文章转来转去,却没有一个说清楚究竟怎么回事。你是不是偶尔也会发现自己曾经很复杂的解决方法,可以用一个巧妙的精简的方法替代,在想自己当初为什么那么笨而想不到。现在好了如果你有刻骨铭心的Nginx经历,别让它被遗忘,欢迎与大家分享,投稿邮箱。
新开Nginx QQ群,欢迎大家一起交流探讨,2000人群号。
如果你喜欢本站,请添加本站链接。
- 126,461 ℃ - 90,009 ℃ - 77,168 ℃ - 74,574 ℃ - 49,164 ℃ - 43,084 ℃ - 39,674 ℃ - 32,823 ℃ - 32,146 ℃ - 25,048 ℃ - 24,748 ℃ - 23,989 ℃ - 22,978 ℃ - 22,883 ℃ - 20,669 ℃

我要回帖

更多关于 肩膀酸痛是怎么回事 的文章

 

随机推荐