为什么 gdb "u" 命令不退出循环?
Why doesn't gdb "u" command exit the loop?
我有一个非常简单的主函数,里面有一个 for 循环,如下所示:
#include<stdio.h>
int main()
{
for(int i=0;i<30;++i)
printf("%d\n",i);
return 0;
}
我试过这样编译它:
gcc 4.c -g
然后我用gdb调试:
$ gdb a.out
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04)...
Reading symbols from a.out...done.
(gdb) list
1 #include<stdio.h>
2 int main()
3 {
4 for(int i=0;i<30;++i)
5 printf("%d\n",i);
6 return 0;
7 }
(gdb) b 5
Breakpoint 1 at 0x400537: file 4.c, line 5.
(gdb) b 6
Breakpoint 2 at 0x400555: file 4.c, line 6.
(gdb) r
Starting program: /home/a/cpp/a.out
Breakpoint 1, main () at 4.c:5
5 printf("%d\n",i);
(gdb) p i
= 0
(gdb) u
0
4 for(int i=0;i<30;++i)
(gdb) u //not exiting for loop?
Breakpoint 1, main () at 4.c:5
5 printf("%d\n",i);
(gdb)
1
4 for(int i=0;i<30;++i)
(gdb) u
似乎 "u" 命令无助于执行整个 for 循环并到达下一个断点,但类似于 "n" 命令。
为什么?对我的描述有什么误解吗?
谢谢
为了理解循环结构,gdb 似乎必须经历一次循环。
(gdb) list
1 #include<stdio.h>
2 int main()
3 {
4 for(int i=0;i<5;++i)
5 {
6 printf("%d\n",i);
7 }
8 return 0;
9 }
10
(gdb) b main
Breakpoint 1 at 0x400535: file junk.cpp, line 4.
(gdb) b 8
Breakpoint 2 at 0x40055c: file junk.cpp, line 8.
(gdb) r
Starting program: /tmp/local/matcher_server/bin/a.out
Breakpoint 1, main () at junk.cpp:4
4 for(int i=0;i<30;++i)
(gdb) n
6 printf("%d\n",i);
(gdb) n
0
4 for(int i=0;i<30;++i)
(gdb) u
1
2
3
4
Breakpoint 2, main () at junk.cpp:8
8 return 0;
要了解原因,我们需要查看 main
的汇编器
(gdb) disass
Dump of assembler code for function main():
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: sub [=11=]x10,%rsp
0x0000000000400535 <+8>: movl [=11=]x0,-0x4(%rbp)
0x000000000040053c <+15>: jmp 0x400556 <main()+41>
0x000000000040053e <+17>: mov -0x4(%rbp),%eax
0x0000000000400541 <+20>: mov %eax,%esi
0x0000000000400543 <+22>: mov [=11=]x4005f4,%edi
0x0000000000400548 <+27>: mov [=11=]x0,%eax
0x000000000040054d <+32>: callq 0x400410 <printf@plt>
=> 0x0000000000400552 <+37>: addl [=11=]x1,-0x4(%rbp)
0x0000000000400556 <+41>: cmpl [=11=]x1d,-0x4(%rbp)
0x000000000040055a <+45>: jle 0x40053e <main()+17>
0x000000000040055c <+47>: mov [=11=]x0,%eax
0x0000000000400561 <+52>: leaveq
0x0000000000400562 <+53>: retq
End of assembler dump.
以及来自 dwarfdump
的行详细信息
.debug_line: line number info for a single cu
Source lines (from CU-DIE at .debug_info offset 0x0000000b):
<pc> [row,col] NS BB ET PE EB IS= DI= uri: "filepath"
NS new statement, BB new basic block, ET end of text sequence
PE prologue end, EB epilogue begin
IA=val ISA number, DI=val discriminator value
0x0040052d [ 3, 0] NS uri: "/tmp/local/matcher_server/bin/junk.cpp"
0x00400535 [ 4, 0] NS
0x0040053e [ 6, 0] NS DI=0x2
0x00400552 [ 4, 0] NS DI=0x2
0x00400556 [ 4, 0] DI=0x1
0x0040055c [ 8, 0] NS
0x00400561 [ 9, 0] NS
0x00400563 [ 9, 0] NS ET
[3,0]列是行号和列号。正如我们所见,循环导致行号不连续,即 3、4、6、4。
我怀疑程序第一次运行到第 6 行并给出 'u' 命令时,gdb 对 DWARF 符号中的循环感到困惑。然而,在第二个循环中,它是正确的。可能是 'u' 命令实现方式的小错误或人工制品。
请注意,在 'u' 命令期间,gdb 仍会遇到断点。在您的示例中,您需要删除 printf 上的断点。
我有一个非常简单的主函数,里面有一个 for 循环,如下所示:
#include<stdio.h>
int main()
{
for(int i=0;i<30;++i)
printf("%d\n",i);
return 0;
}
我试过这样编译它:
gcc 4.c -g
然后我用gdb调试:
$ gdb a.out
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04)...
Reading symbols from a.out...done.
(gdb) list
1 #include<stdio.h>
2 int main()
3 {
4 for(int i=0;i<30;++i)
5 printf("%d\n",i);
6 return 0;
7 }
(gdb) b 5
Breakpoint 1 at 0x400537: file 4.c, line 5.
(gdb) b 6
Breakpoint 2 at 0x400555: file 4.c, line 6.
(gdb) r
Starting program: /home/a/cpp/a.out
Breakpoint 1, main () at 4.c:5
5 printf("%d\n",i);
(gdb) p i
= 0
(gdb) u
0
4 for(int i=0;i<30;++i)
(gdb) u //not exiting for loop?
Breakpoint 1, main () at 4.c:5
5 printf("%d\n",i);
(gdb)
1
4 for(int i=0;i<30;++i)
(gdb) u
似乎 "u" 命令无助于执行整个 for 循环并到达下一个断点,但类似于 "n" 命令。
为什么?对我的描述有什么误解吗? 谢谢
为了理解循环结构,gdb 似乎必须经历一次循环。
(gdb) list
1 #include<stdio.h>
2 int main()
3 {
4 for(int i=0;i<5;++i)
5 {
6 printf("%d\n",i);
7 }
8 return 0;
9 }
10
(gdb) b main
Breakpoint 1 at 0x400535: file junk.cpp, line 4.
(gdb) b 8
Breakpoint 2 at 0x40055c: file junk.cpp, line 8.
(gdb) r
Starting program: /tmp/local/matcher_server/bin/a.out
Breakpoint 1, main () at junk.cpp:4
4 for(int i=0;i<30;++i)
(gdb) n
6 printf("%d\n",i);
(gdb) n
0
4 for(int i=0;i<30;++i)
(gdb) u
1
2
3
4
Breakpoint 2, main () at junk.cpp:8
8 return 0;
要了解原因,我们需要查看 main
的汇编器(gdb) disass
Dump of assembler code for function main():
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: sub [=11=]x10,%rsp
0x0000000000400535 <+8>: movl [=11=]x0,-0x4(%rbp)
0x000000000040053c <+15>: jmp 0x400556 <main()+41>
0x000000000040053e <+17>: mov -0x4(%rbp),%eax
0x0000000000400541 <+20>: mov %eax,%esi
0x0000000000400543 <+22>: mov [=11=]x4005f4,%edi
0x0000000000400548 <+27>: mov [=11=]x0,%eax
0x000000000040054d <+32>: callq 0x400410 <printf@plt>
=> 0x0000000000400552 <+37>: addl [=11=]x1,-0x4(%rbp)
0x0000000000400556 <+41>: cmpl [=11=]x1d,-0x4(%rbp)
0x000000000040055a <+45>: jle 0x40053e <main()+17>
0x000000000040055c <+47>: mov [=11=]x0,%eax
0x0000000000400561 <+52>: leaveq
0x0000000000400562 <+53>: retq
End of assembler dump.
以及来自 dwarfdump
.debug_line: line number info for a single cu
Source lines (from CU-DIE at .debug_info offset 0x0000000b):
<pc> [row,col] NS BB ET PE EB IS= DI= uri: "filepath"
NS new statement, BB new basic block, ET end of text sequence
PE prologue end, EB epilogue begin
IA=val ISA number, DI=val discriminator value
0x0040052d [ 3, 0] NS uri: "/tmp/local/matcher_server/bin/junk.cpp"
0x00400535 [ 4, 0] NS
0x0040053e [ 6, 0] NS DI=0x2
0x00400552 [ 4, 0] NS DI=0x2
0x00400556 [ 4, 0] DI=0x1
0x0040055c [ 8, 0] NS
0x00400561 [ 9, 0] NS
0x00400563 [ 9, 0] NS ET
[3,0]列是行号和列号。正如我们所见,循环导致行号不连续,即 3、4、6、4。
我怀疑程序第一次运行到第 6 行并给出 'u' 命令时,gdb 对 DWARF 符号中的循环感到困惑。然而,在第二个循环中,它是正确的。可能是 'u' 命令实现方式的小错误或人工制品。
请注意,在 'u' 命令期间,gdb 仍会遇到断点。在您的示例中,您需要删除 printf 上的断点。