1. gcov是什麼?
- Gcov is GCC Coverage
- 是一個測試代碼覆寫率的工具
- 是一個指令行方式的控制台程式
- 伴随GCC釋出,配合GCC共同實作對C/C++檔案的語句覆寫和分支覆寫測試;
- 與程式概要分析工具(profiling tool,例如gprof)一起工作,可以估計程式中哪一段代碼最耗時;
注:程式概要分析工具是分析代碼性能的工具。
2. gcov能做什麼?
gcov可以統計
- 每一行代碼的執行頻率
- 實際上哪些代碼确實被執行了
- 每一段代碼(section code)的耗時(執行時間)
是以,gcov可以幫你優化代碼,當然這個優化動作還是應該有開發者完成。
3. 如何使用gcov?
#include <iostream>
using namespace std;
int main()
{
int i,total;
total = 0;
for (i=0; i<10; i++)
total += i;
if (total != 45)
cout << "Failure!" << endl;
else
cout << "Success!" << endl;
return 0;
}
3.1 使用gcov的3個階段
(1) 編譯
$ g++ -fprofile-arcs -ftest-coverage -o main main.cpp
$ ls
-rwxrwxr-x. 1 heli heli 20281 Dec 7 11:54 main
-rw-rw-r--. 1 heli heli 217 Dec 7 10:57 main.cpp
-rw-rw-r--. 1 heli heli 6632 Dec 7 11:54 main.gcno
-fprofile-arcs -ftest-coverage告訴編譯器生成gcov需要的額外資訊,并在目标檔案中插入gcov需要的extra
profiling information。是以,該指令在生成可執行檔案test的同時生成mian.gcno檔案(gcov
note檔案)。
(2) 收集資訊
執行該程式,生成main.gcda檔案(gcov data檔案)。
(3) 報告
$ ./main Success! $ ll total 36 -rwxrwxr-x. 1 heli heli 20281 Dec 7 11:54 main -rw-rw-r--. 1 heli heli 217 Dec 7 10:57 main.cpp -rw-rw-r--. 1 heli heli 784 Dec 7 11:56 main.gcda -rw-rw-r--. 1 heli heli 6632 Dec 7 11:54 main.gcno
$ gcov main.cpp File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h' Lines executed:0.00% of 2 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h:creating 'ios_base.h.gcov' File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream' Lines executed:0.00% of 11 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream:creating 'ostream.gcov' File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/basic_ios.h' Lines executed:0.00% of 10 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/basic_ios.h:creating 'basic_ios.h.gcov' File 'main.cpp' Lines executed:88.89% of 9 main.cpp:creating 'main.cpp.gcov' File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream' Lines executed:100.00% of 1 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream:creating 'iostream.gcov' File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h' Lines executed:0.00% of 2 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h:creating 'char_traits.h.gcov' File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_facets.h' Lines executed:0.00% of 5 /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_facets.h:creating 'locale_facets.h.gcov'
$ ll total 300 -rw-rw-r--. 1 heli heli 22753 Dec 7 11:57 basic_ios.h.gcov -rw-rw-r--. 1 heli heli 25834 Dec 7 11:57 char_traits.h.gcov -rw-rw-r--. 1 heli heli 44130 Dec 7 11:57 ios_base.h.gcov -rw-rw-r--. 1 heli heli 4084 Dec 7 11:57 iostream.gcov -rw-rw-r--. 1 heli heli 132403 Dec 7 11:57 locale_facets.h.gcov -rwxrwxr-x. 1 heli heli 20281 Dec 7 11:54 main -rw-rw-r--. 1 heli heli 217 Dec 7 10:57 main.cpp -rw-rw-r--. 1 heli heli 618 Dec 7 11:57 main.cpp.gcov -rw-rw-r--. 1 heli heli 784 Dec 7 11:56 main.gcda -rw-rw-r--. 1 heli heli 6632 Dec 7 11:54 main.gcno -rw-rw-r--. 1 heli heli 27743 Dec 7 11:57 ostream.gcov
生成:
main.cpp.gcov
檔案,該檔案記錄了每行代碼被執行的次數。
main.cpp.gcov檔案内容如下:
-: 0:Source:main.cpp
-: 0:Graph:main.gcno
-: 0:Data:main.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <iostream>
-: 2:using namespace std;
1: 3:int main()
-: 4:{
-: 5: int i,total;
1: 6: total = 0;
-: 7:
11: 8: for (i=0; i<10; i++)
10: 9: total += i;
-: 10:
1: 11: if (total != 45)
#####: 12: cout << "Failure!" << endl;
-: 13: else
1: 14: cout << "Success!" << endl;
1: 15: return 0;
3: 16:}
3.2 gcov的選項
gcov的選項不多,也好了解,此處選3個典型的選項并結合例子加以說明。
(1) -a, --all-blocks
在.gcov檔案中輸出每個基本快(basic block)的執行次數。如果沒有-a選項,則輸出'main'函數這個block的執行次數,如上所示。使用該選項可以
Write individual execution counts for every basic block. Normally gcov outputs execution counts only for the main blocks of a line. With this option you can determine if blocks within
a single line are not being executed.
# gcov -a main.cpp
$ gcov -a main.cpp
File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h'
Lines executed:0.00% of 2
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h:creating 'ios_base.h.gcov'
File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream'
Lines executed:0.00% of 11
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream:creating 'ostream.gcov'
File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/basic_ios.h'
Lines executed:0.00% of 10
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/basic_ios.h:creating 'basic_ios.h.gcov'
File 'main.cpp'
Lines executed:88.89% of 9
main.cpp:creating 'main.cpp.gcov'
File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream'
Lines executed:100.00% of 1
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream:creating 'iostream.gcov'
File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h'
Lines executed:0.00% of 2
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h:creating 'char_traits.h.gcov'
File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_facets.h'
Lines executed:0.00% of 5
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_facets.h:creating 'locale_facets.h.gcov'
main.cpp.gcov檔案内容。
-: 0:Source:main.cpp
-: 0:Graph:main.gcno
-: 0:Data:main.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <iostream>
-: 2:using namespace std;
1: 3:int main()
-: 4:{
-: 5: int i,total;
1: 6: total = 0;
-: 7:
11: 8: for (i=0; i<10; i++)
1: 8-block 0
10: 8-block 1
11: 8-block 2
10: 9: total += i;
-: 10:
1: 11: if (total != 45)
1: 11-block 0
#####: 12: cout << "Failure!" << endl;
$$$$$: 12-block 0
-: 13: else
1: 14: cout << "Success!" << endl;
1: 14-block 0
1: 15: return 0;
1: 15-block 0
3: 16:}
1: 16-block 0
1: 16-block 1
1: 16-block 2
1: 16-block 3
(2) -b, --branch-probabilities
在.gcov檔案中輸出每個分支的執行頻率,并有分支統計資訊。
# gcov -b main.cpp
(3) -c, --branch-counts
在.gcov檔案中輸出每個分支的執行次數。
# gcov -c main.cpp