GDB是调试利器,在某些场景下,不确定是否好用,今天特意测试了在虚函数,内联函数,函数模板的使用
#include <iostream>
using namespace std;
class Base
{
public:
virtual void test(){
cout << "i am base" << endl;
}
};
class Derived: public Base
{
private:
int a_;
public:
inline void testInline(int b)
{
a_++;
a_ += b;
a_ += 7;
}
void callInline()
{
int b = 111;
testInline(b);
}
virtual void test() override {
cout << "i am Derived" << endl;
}
};
template<typename T>
T MaxElement(T a, T b, T c)
{
T tmp = a;
if (tmp < b) {
tmp = b;
}
if (tmp < c) {
tmp = c;
}
cout << "max element: " << tmp << endl;
return tmp;
}
int main()
{
double maxDouble = MaxElement(1.2, 3.0, -3.2);
float maxFloat = MaxElement(121.2f, 23.0f, -31.2f);
int maxInt = MaxElement(1,2,3);
Derived d;
d.test();
d.callInline();
return 0;
}
aaa@ubuntu:~/share$ g++ -std=c++11 -g main.cpp -o main
aaa@ubuntu:~/share$ gdb main
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
(gdb) b MaxElement #对于模板函数,这样是不行滴
Function "MaxElement" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (MaxElement) pending.
(gdb) b MaxElement<int> #需要这样子
Breakpoint 2 at 0x400db4: file main.cpp, line 37.
(gdb) b MaxElement<double> #需要这样子
Breakpoint 3 at 0x400cae: file main.cpp, line 37.
(gdb) b MaxElement<float> #需要这样子
Breakpoint 4 at 0x400d36: file main.cpp, line 37.
(gdb) b MaxElement<short> #因为没有short的调用,也不行
Function "MaxElement<short>" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) b Derived::testInline #inline函数断点
Breakpoint 5 at 0x400bcb: file main.cpp, line 19.
(gdb) b Derived::test #虚函数断点
Breakpoint 6 at 0x400c38: file main.cpp, line 30.
(gdb) r
Starting program: /home/cherish/share/main
Breakpoint 3, MaxElement<double> (a=1.2, b=3, c=-3.2000000000000002) at main.cpp:37
37 T tmp = a;
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) n
Program not restarted.
(gdb) c
Continuing.
max element: 3
Breakpoint 4, MaxElement<float> (a=121.199997, b=23, c=-31.2000008) at main.cpp:37
37 T tmp = a;
(gdb) c
Continuing.
max element: 121.2
Breakpoint 2, MaxElement<int> (a=1, b=2, c=3) at main.cpp:37
37 T tmp = a;
(gdb) c
Continuing.
max element: 3
Breakpoint 6, Derived::test (this=0x7fffffffe480) at main.cpp:30
30 cout << "i am Derived" << endl;
(gdb) c
Continuing.
i am Derived
Breakpoint 5, Derived::testInline (this=0x7fffffffe480, b=111) at main.cpp:19
19 a_++;
(gdb) c
Continuing.
[Inferior 1 (process 4921) exited normally]
(gdb) c
对于模板函数,还有一个黑科技,一次设置所有类型的断点(rbreak)。这里看到,通过这个命令可以一次性把MaxElement实例的函数都设置了断点。
(gdb) rbreak MaxElement<.*>
Breakpoint 7 at 0x400cae: file main.cpp, line 37.
double MaxElement<double>(double, double, double);
Note: breakpoint 4 also set at pc 0x400d36.
Breakpoint 8 at 0x400d36: file main.cpp, line 37.
float MaxElement<float>(float, float, float);
Breakpoint 9 at 0x400db4: file main.cpp, line 37.
int MaxElement<int>(int, int, int);
在函数模板里,如果我们仅仅对某个类型的实例设置断点,那么其他类型的实例在允许时是不会暂停的。如下
aaa@ubuntu:~/share$ gdb main
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
(gdb) info b
No breakpoints or watchpoints.
(gdb) b MaxElement<float>
Breakpoint 1 at 0x400d36: file main.cpp, line 37.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400d36 in MaxElement<float>(float, float, float) at main.cpp:37
(gdb) r
Starting program: /home/cherish/share/main
max element: 3Breakpoint 1, MaxElement<float> (a=121.199997, b=23, c=-31.2000008) at main.cpp:37
37 T tmp = a;
(gdb) c
Continuing.
max element: 121.2
max element: 3
i am Derived
[Inferior 1 (process 4937) exited normally]
最后如果去除了符号表,那么是如设置断点的,如下:
aaa@ubuntu:~/share$ g++ -std=gnu++11 main.cpp -o main_with_sym
aaa@ubuntu:~/share$ g++ -std=gnu++11 -s main.cpp -o main_without_sym #去除符号表
aaa@ubuntu:~/share$ ls -l main*
-rwxrw-rw- 1 aaa aaa 816 Mar 12 08:06 main.cpp
-rwxrwxr-x 1 aaa aaa 10488 Mar 12 08:54 main_without_sym
-rwxrwxr-x 1 aaa aaa 14448 Mar 12 08:54 main_with_sym
aaa@ubuntu:~/share$ objdump -t main_without_sym
main_without_sym: file format elf64-x86-64
SYMBOL TABLE:
no symbols
aaa@ubuntu:~/share$ objdump -t main_with_sym
main_with_sym: file format elf64-x86-64
SYMBOL TABLE:
0000000000400238 l d .interp 0000000000000000 .interp
0000000000400254 l d .note.ABI-tag 0000000000000000 .note.ABI-tag
......
0000000000400bc0 w F .text 0000000000000043 _ZN7Derived10testInlineEi
0000000000400e80 g F .text 0000000000000002 __libc_csu_fini
0000000000400c2c w F .text 000000000000002b _ZN7Derived4testEv
0000000000400980 g F .text 000000000000002a _start
0000000000000000 w *UND* 0000000000000000 __gmon_start__
0000000000000000 w *UND* 0000000000000000 _Jv_RegisterClasses
0000000000400c70 w F .text 0000000000000027 _ZN7DerivedC1Ev
0000000000400e84 g F .fini 0000000000000000 _fini
0000000000000000 F *UND* 0000000000000000 _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
0000000000000000 F *UND* 0000000000000000 __libc_start_main@@GLIBC_2.2.5
0000000000400d1f w F .text 0000000000000084 _Z10MaxElementIfET_S0_S0_S0_
0000000000400f10 w O .rodata 0000000000000018 _ZTI7Derived
0000000000000000 F *UND* 0000000000000000 __cxa_atexit@@GLIBC_2.2.5
0000000000400910 F *UND* 0000000000000000 _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
0000000000000000 w *UND* 0000000000000000 _ITM_deregisterTMCloneTable
0000000000000000 F *UND* 0000000000000000 _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@@GLIBCXX_3.4
0000000000400e90 g O .rodata 0000000000000004 _IO_stdin_used
0000000000400c58 w F .text 0000000000000017 _ZN4BaseC1Ev
0000000000000000 w *UND* 0000000000000000 _ITM_registerTMCloneTable
0000000000602070 g .data 0000000000000000 __data_start
0000000000400ee0 w O .rodata 0000000000000018 _ZTV7Derived
0000000000400da3 w F .text 0000000000000064 _Z10MaxElementIiET_S0_S0_S0_
0000000000602080 w O .bss 0000000000000058 _ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3
0000000000400c97 w F .text 0000000000000088 _Z10MaxElementIdET_S0_S0_S0_
......
00000000006021f0 w O .bss 0000000000000058 _ZTVN10__cxxabiv120__si_class_type_infoE@@CXXABI_1.3
0000000000400c04 w F .text 0000000000000027 _ZN7Derived10callInlineEv
0000000000000000 F *UND* 0000000000000000 __stack_chk_fail@@GLIBC_2.4
0000000000000000 F *UND* 0000000000000000 _ZNSolsEf@@GLIBCXX_3.4
0000000000400b94 w F .text 000000000000002b _ZN4Base4testEv
0000000000602250 g .bss 0000000000000000 _end
0000000000000000 F *UND* 0000000000000000 _ZNSolsEPFRSoS_E@@GLIBCXX_3.4
0000000000400c58 w F .text 0000000000000017 _ZN4BaseC2Ev
0000000000400960 F *UND* 0000000000000000 _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@@GLIBCXX_3.4
0000000000400ef8 w O .rodata 0000000000000018 _ZTV4Base
0000000000602080 g .data 0000000000000000 _edata
0000000000400a76 g F .text 00000000000000ca main
0000000000400888 g F .init 0000000000000000 _init
aaa@ubuntu:~/share$ gdb ./main
main.cpp main_without_sym main_with_sym
aaa@ubuntu:~/share$ gdb ./main_without_sym
(gdb) b main
Function "main" not defined. #找不到函数
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (main) pending.
(gdb) r #直接执行完毕
Starting program: /home/aaa/share/main_without_sym
max element: 3
max element: 121.2
max element: 3
i am Derived
[Inferior 1 (process 5180) exited normally]
(gdb) q
aaa@ubuntu:~/share$ gdb ./main_with_sym
(gdb) b main
Breakpoint 1 at 0x400a7a #找到函数
(gdb) r
Starting program: /home/aaa/share/main_with_sym
Breakpoint 1, 0x0000000000400a7a in main () #停在断点
(gdb) c
Continuing.
max element: 3
max element: 121.2
max element: 3
i am Derived
[Inferior 1 (process 5186) exited normally]
(gdb)