首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Linux on Power 上的调试工具和技术(3)

Linux on Power 上的调试工具和技术(3)

清单 12. gdbtest1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
54                       } else {
55                               temp->SetNext (current->GetNext());
56                               delete temp;
57                               temp = 0;
58                               return 0;
59                       }
60               }
61               current = 0;
62               temp = current;
63               current = current->GetNext();
64       }
65
66       return -1;




第 61 行 current=0 将这个指针设置为一个无效的地址,这正是产生段错误的根源。注释掉第 61 行,将其保存为 gdbtest2.cpp,然后编译并重新运行。
清单 13. 再次运行程序(gdbtest2.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# g++ -g -o gdbtest2 gdbtest2.cpp
# ./gdbtest2
Number Box "0" created
Number Box "1" created
Number Box "2" created
Number Box "3" created
Number Box "4" created
Number Box "5" created
Number Box "6" created
Number Box "7" created
Number Box "8" created
Number Box "9" created
list created
Number Box "9" deleted
Number Box "0" deleted




这个程序现在可以成功完成而不会出现段错误了。然而,结果并不像我们预期的一样:程序在删除 Number Box "9"之后删除了 Number Box "0",而不像我们期望的一样删除 Number Box "8,"。使用 gdb 再次来看一下。
清单 14. 再次使用 gdb 进行查看
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# gdb ./gdbtest2
GNU gdb 6.2.1
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you
are welcome to change it and/or 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.
This GDB was configured as "ppc-suse-linux"...Using host libthread_db
library "/lib/tls/libthread_db.so.1".
(gdb) break 94 if i==8
Breakpoint 1 at 0x10000968: file gdbtest2.cpp, line 94.
(gdb) run
Starting program: /root/test/gdbtest2
Number Box "0" created
Number Box "1" created
Number Box "2" created
Number Box "3" created
Number Box "4" created
Number Box "5" created
Number Box "6" created
Number Box "7" created
Number Box "8" created
Number Box "9" created
list created
Number Box "9" deleted
Breakpoint 1, main (argc=1, argv=0xffffe554) at gdbtest2.cpp:94
94                      list ->RemoveBox(i);




您可能希望找出为什么这个程序删除的是 Number Box 0,而不是 Number Box 8,因此需要在您认为程序会删除 Number Box 8 的地方停止程序。设置这个断点:break 94 if i==8,可以在 i 等于 8 时在第 94 行处停止程序。然后单步跟踪到 RemoveBox() 函数中。
清单 15. 单步跟踪到 RemoveBox() 函数中
1
2
3
4
5
6
7
8
9
(gdb) s
38                      NumBox<T> *temp = 0;  
(gdb) s
40                      while (current != 0) {
(gdb) print pointer
$1 = (NumBox<int> *) 0x100120a8
(gdb) print *pointer
$2 = {Num = 0, Next = 0x0}
(gdb)




指针早已指向了 Number Box "0",因此这个 bug 可能就存在于程序删除 Number Box "9" 的地方。要在 gdb 中重新启动这个程序,请使用 kill 删除原来的断点,然后添加一个 i 等于 9 时的新断点,然后再次运行这个程序。
清单 16.  在 gdb 中重新启动程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(gdb) kill
Kill the program being debugged? (y or n) y
(gdb) info break
Num Type           Disp Enb Address    What
1   breakpoint     keep y   0x10000968 in main at gdbtest2.cpp:94
        stop only if i == 8
        breakpoint already hit 1 time
(gdb) delete 1
(gdb) break 94 if i==9
Breakpoint 2 at 0x10000968: file gdbtest2.cpp, line 94.
(gdb) run
Starting program: /root/test/gdbtest2
Number Box "0" created
Number Box "1" created
Number Box "2" created
Number Box "3" created
Number Box "4" created
Number Box "5" created
Number Box "6" created
Number Box "7" created
Number Box "8" created
Number Box "9" created
list created
Breakpoint 2, main (argc=1, argv=0xffffe554) at gdbtest2.cpp:94
94                      list ->RemoveBox(i);
(gdb)




当这一次单步跟踪 RemoveBox() 函数时,要特别注意 list->pointer 正在指向哪一个数字框,因为 bug 可能就在于 list->pointer 开始指向 Number Box "0" 的地方。请使用 display *pointer 命令来查看,这会自动显示这个函数。
清单 17.  使用 display *pointer 命令进行监视
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Breakpoint 2, main (argc=1, argv=0xffffe554) at gdbtest2.cpp:94
94            list ->RemoveBox(i);
(gdb) s
NumChain<int>::RemoveBox (this=0x10012008, item_to_remove=@0xffffe200) <br>
at gdbtest2.cpp:37
37            NumBox<T> *current = pointer;
(gdb) display *pointer
1: *this->pointer = {Num = 9, Next = 0x10012098}
(gdb) s
38            NumBox<T> *temp = 0;  
1: *this->pointer = {Num = 9, Next = 0x10012098}
(gdb) s
40            while (current != 0) {
1: *this->pointer = {Num = 9, Next = 0x10012098}
(gdb) s
41                    if (current->GetValue() == item_to_remove) {
1: *this->pointer = {Num = 9, Next = 0x10012098}
(gdb) s
NumBox<int>::GetValue (this=0x100120a8) at gdbtest2.cpp:16
16            const T& GetValue () const { return Num; }
(gdb) s
NumChain<int>::RemoveBox (this=0x10012008, item_to_remove=@0xffffe200) <br>
at gdbtest2.cpp:42
42                       if (temp == 0) {
1: *this->pointer = {Num = 9, Next = 0x10012098}
(gdb) s
44                               if (current->GetNext() == 0) {
1: *this->pointer = {Num = 9, Next = 0x10012098}
(gdb) s
NumBox<int>::GetNext (this=0x100120a8) at gdbtest2.cpp:14
14            NumBox<T>*GetNext() const { return Next; }
(gdb) s
NumChain<int>::RemoveBox (this=0x10012008, item_to_remove=@0xffffe200) <br>
at gdbtest2.cpp:50
50                                            delete current;
1: *this->pointer = {Num = 9, Next = 0x10012098}
(gdb) s
~NumBox (this=0x100120a8) at gdbtest2.cpp:10
10            std::cout << "Number Box " <<"\""  << GetValue() <br>
<<"\""  <<" deleted" << std::endl;
(gdb) s
NumBox<int>::GetValue (this=0x100120a8) at gdbtest2.cpp:16
16            const T& GetValue () const { return Num; }
(gdb) s
Number Box "9" deleted
~NumBox (this=0x100120a8) at gdbtest2.cpp:11
11            Next = 0;
(gdb) s
NumChain<int>::RemoveBox (this=0x10012008, item_to_remove=@0xffffe200) <br>
at gdbtest2.cpp:51
51                                           current = 0;
1: *this->pointer = {Num = 0, Next = 0x0}
(gdb) s
53                                    return 0;
1: *this->pointer = {Num = 0, Next = 0x0}
(gdb) s
0x10000d1c      66                      return -1;
1: *this->pointer = {Num = 0, Next = 0x0}




从上面的跟踪过程中,您可以看到 list->pointer 在删除 Number Box "9" 之后指向了 Number Box "0"。这个逻辑并不正确,因为在删除 Number Box "9" 之后,list->pointer 应该指向的是 Number Box "8"。现在非常显然我们应该在第 50 行之前添加一条语句 pointer = pointer->GetNext();,如下所示:
清单 18. 在第 50 行之前添加一条 pointer = pointer->GetNext(); 语句
1
2
3
4
5
6
49                     } else {
50                             pointer = pointer->GetNext();
51                             delete current;
52                             current = 0;
53                      }
54                      return 0;




将新修改之后的程序保存为 gdbtest3.cpp,然后编译并再次运行。
清单 19. 再次运行程序(gdbtest3.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# g++ -g -o gdbtest3 gdbtest3.cpp
# ./gdbtest3
Number Box "0" created
Number Box "1" created
Number Box "2" created
Number Box "3" created
Number Box "4" created
Number Box "5" created
Number Box "6" created
Number Box "7" created
Number Box "8" created
Number Box "9" created
list created
Number Box "9" deleted
Number Box "8" deleted
Number Box "7" deleted
Number Box "6" deleted
Number Box "5" deleted
Number Box "4" deleted
Number Box "3" deleted
Number Box "2" deleted
Number Box "1" deleted
Number Box "0" deleted




这才是我们期望的结果。
返回列表