gdb调试Tips

 

step into就是单步执行,遇到子函数就进入并且继续单步执行;
step over是在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完再停止,也就是把子函数整个作为一步。
step out就是但单步执行到子函数内时,用step out就可以执行完子函数余下部分,并返回到上一层函
数。

step into:进入子函数      
step over:越过子函数,但子函数会执行
step out:跳出子函数  

Step Into

Executes code one statement at a time.

When not in design mode, Step Into enters break mode at the current line of execution. Step Into executes the statement at the current execution point. If the statement is a call to a procedure, the next statement displayed is the first statement in the procedure.

At design time, this menu item begins execution and enters break modebreak mode before the first line of code is executed. Not available at run time.

If there is no current execution point, the Step Into command may appear to do nothing until you do something that triggers code, for example click on a document.

Toolbar button: . Keyboard shortcut:  F10.

Step Over

Similar to Step Into. The difference in use occurs when the current statement contains a call to a procedure.

Step Over executes the procedure as a unit, and then steps to the next statement in the current procedure. Therefore, the next statement displayed is the next statement in the current procedure regardless of whether the current statement is a call to another procedure. Available in break mode only.

Toolbar button:  . Keyboard shortcut:  F11.

Step Out

Executes the remaining lines of a function in which the current execution point lies. The next statement displayed is the statement following the procedure call. All of the code is executed between the current and the final execution points. Available in break mode only.

Toolbar button:  . Keyboard shortcut:  SHIFT+F11

GDB中

step ->    step into:进入子函数      
next ->     step over:越过子函数,但子函数会执行
finish->   step out:跳出子函数

until->   同step over,主要用于退出循环 

_________________

原文件编译的时候要加-g,例gcc -g -o test test.c, 这样在能在调试的时候用list,watch等命令。

全局变量或当前堆栈区可见的变量才能watch,watch之后用Continuing,就可显示观察变量。



gdb watch 跟踪变量的变化


01 #include <stdio.h>
02 #include <stdlib.h>
03 #include <string.h>
04 
05 int main()
06 {
07     char * name = NULL;
08     int len = 10;
09 
10     name = (char *)malloc(len);
11     strncpy(name, "zengxiaolong", len);
12 
13     char ** wild_pointer;
14     wild_pointer = &name;          // 野指针,指向了变量name
15     *wild_pointer = (char *)0x100; // 野指针,破坏了变量name
16 
17     name[0] = 'a';
18     return 0;
19 }

# gcc test.c -o test -g
# gdb -q test
(gdb) l
1    #include <stdio.h>
2    #include <stdlib.h>
3    #include <string.h>
4    
5    int main()
6    {
7        char * name = NULL;
8        int len = 10;
9    
10        name = (char *)malloc(len);
(gdb) b 7
Breakpoint 1 at 0x80483b5: file test.c, line 7.
(gdb) r
Starting program: /tftpboot/test 

Breakpoint 1, main () at test.c:7
7        char * name = NULL;
(gdb) watch name // 跟踪变量name变化情况
Hardware watchpoint 2: name // 说明该系统结构支持硬件断点
(gdb) c
Continuing.
Hardware watchpoint 2: name

Old value = 0xb7f79dc0 "U\211�WVS��y" // 这里变量name发生了变化
New value = 0x804a008 ""

main () at test.c:11
11        strncpy(name, "zengxiaolong", len);
(gdb) c
Continuing.
Hardware watchpoint 2: name

Old value = 0x804a008 "zengxiaolo"
New value = 0x100 <Address 0x100 out of bounds> // 指针越界了

main () at test.c:17
17        name[0] = 'a';
(gdb)c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x080483fd in main () at test.c:17
17        name[0] = 'a';
(gdb) 

 

譬如建立新文件Watch.c

#include <stdio.h>

int main()
{
    sleep(10);
    printf("Waiting...");

    int i;   
    for(i=0; i<100; i++)
    {  
        printf("I'm %u.\n", i);
    }  
   
    return 0;
}

 

然后  gcc  -g test.c -o test

然后 gdb调试test

在int i;设置断点,此时不能将i设为watchpoint,因为不再context中

(gdb) info b
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x00401082 in main at watch.c:8
(gdb) watch i
No symbol "i" in current context.

 

运行程序,当i在context中时添加watchpoint,

此时如果变化则会显示watchpoint的变化,并且停止下来,用continue可以继续

(gdb) r   
Starting program: /home/yueshen/a.exe
[New thread 2484.0x11b4]
[New thread 2484.0x1220]

Breakpoint 2, main () at watch.c:9
(gdb) n
(gdb) watch i
Hardware watchpoint 3: i
(gdb) info b
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x00401082 in main at watch.c:8
        breakpoint already hit 1 time
3       hw watchpoint  keep y              i
(gdb) c
Continuing.
Waiting...I'm 0.
Hardware watchpoint 3: i

Old value = 0
New value = 1
0x004010a7 in main () at watch.c:9
(gdb) c
I'm 1.
Continuing.
Hardware watchpoint 3: i

Old value = 1
New value = 2
0x004010a7 in main () at watch.c:9




gdb中看内存(x命令)

你可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示:

x/<n/f/u> <addr>

n、f、u是可选的参数。

n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。

f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。

u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字 节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。

bhwg

x/4bt &a

--------------------------------
<addr>表示一个内存地址。
n/f/u三个参数可以一起使用。例如:

命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。

输出格式
一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显示格式:

x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。



 

转载于:https://my.oschina.net/alphajay/blog/42851

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值