測試代碼覆蓋率-GCOV的使用


1. gcov是什麼?
  • Gcov is GCC Coverage
  • 是一個測試代碼覆蓋率的工具
  • 是一個命令行方式的控制檯程序
  • 伴隨GCC發佈配合GCC共同實現對C/C++文件的語句覆蓋和分支覆蓋測試
  • 與程序概要分析工具(profiling tool,例如gprof)一起工作,可以估計程序中哪一段代碼最耗時;

注:程序概要分析工具是分析代碼性能的工具。

2. gcov能做什麼?

gcov可以統計

  • 每一行代碼的執行頻率
  • 實際上哪些代碼確實被執行了
  • 每一段代碼(section code)的耗時(執行時間)

因此,gcov可以幫你優化代碼,當然這個優化動作還是應該有開發者完成。

 

3. 如何使用gcov

  1. #include <iostream>  
  2. using namespace std;  
  3. int main()  
  4. {  
  5.     int i,total;  
  6.     total = 0;  
  7.     for (i=0; i<10; i++)  
  8.         total += i;  
  9.     if (total != 45)  
  10.         cout << "Failure!" << endl;  
  11.     else  
  12.         cout << "Success!" << endl;  
  13.     return 0;  
  14. }  
#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 使用gcov3個階段

(1) 編譯

             

  1. <strong>     </strong>$ g++ -fprofile-arcs -ftest-coverage -o main main.cpp  
<strong>     </strong>$ g++ -fprofile-arcs -ftest-coverage -o main main.cpp
  1. <span style="font-family: Arial; font-size: 14px;">          $   ls</span>  
<span style="font-family: Arial; font-size: 14px;">          $   ls</span>

  1. -rwxrwxr-x. 1 heli heli 20281 Dec  7 11:54 main  
  2. -rw-rw-r--. 1 heli heli   217 Dec  7 10:57 main.cpp  
  3. -rw-rw-r--. 1 heli heli  6632 Dec  7 11:54 <strong>main.gcno</strong>  
-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 <strong>main.gcno</strong>

-fprofile-arcs  -ftest-coverage告訴編譯器生成gcov需要的額外信息,並在目標文件中插入gcov需要的extra profiling information。因此,該命令在生成可執行文件test的同時生成mian.gcno文件(gcov note文件)

(2) 收集信息


執行該程序,生成main.gcda文件(gcov data文件)

 

(3) 報告

  1. $ ./main   
  2. Success!  
  3. $ ll  
  4. total 36  
  5. -rwxrwxr-x. 1 heli heli 20281 Dec  7 11:54 main  
  6. -rw-rw-r--. 1 heli heli   217 Dec  7 10:57 main.cpp  
  7. -rw-rw-r--. 1 heli heli   784 Dec  7 11:56 <strong>main.gcda</strong>  
  8. -rw-rw-r--. 1 heli heli  6632 Dec  7 11:54 <strong>main.gcno</strong>  
$ ./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 <strong>main.gcda</strong>
-rw-rw-r--. 1 heli heli  6632 Dec  7 11:54 <strong>main.gcno</strong>
  1. $ gcov main.cpp   
  2. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h'  
  3. Lines executed:0.00% of 2  
  4. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h:creating 'ios_base.h.gcov'  
  5.   
  6. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream'  
  7. Lines executed:0.00% of 11  
  8. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream:creating 'ostream.gcov'  
  9.   
  10. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/basic_ios.h'  
  11. Lines executed:0.00% of 10  
  12. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/basic_ios.h:creating 'basic_ios.h.gcov'  
  13.   
  14. File 'main.cpp'  
  15. Lines executed:88.89% of 9  
  16. main.cpp:creating 'main.cpp.gcov'  
  17.   
  18. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream'  
  19. Lines executed:100.00% of 1  
  20. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream:creating 'iostream.gcov'  
  21.   
  22. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h'  
  23. Lines executed:0.00% of 2  
  24. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h:creating 'char_traits.h.gcov'  
  25.   
  26. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_facets.h'  
  27. Lines executed:0.00% of 5  
  28. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_facets.h:creating 'locale_facets.h.gcov'  
$ 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'
  1. $ ll  
  2. total 300  
  3. -rw-rw-r--. 1 heli heli  22753 Dec  7 11:57 basic_ios.h.gcov  
  4. -rw-rw-r--. 1 heli heli  25834 Dec  7 11:57 char_traits.h.gcov  
  5. -rw-rw-r--. 1 heli heli  44130 Dec  7 11:57 ios_base.h.gcov  
  6. -rw-rw-r--. 1 heli heli   4084 Dec  7 11:57 iostream.gcov  
  7. -rw-rw-r--. 1 heli heli 132403 Dec  7 11:57 locale_facets.h.gcov  
  8. -rwxrwxr-x. 1 heli heli  20281 Dec  7 11:54 main  
  9. -rw-rw-r--. 1 heli heli    217 Dec  7 10:57 main.cpp  
  10. -rw-rw-r--. 1 heli heli    618 Dec  7 11:57 <strong>main.cpp.gcov</strong>  
  11. -rw-rw-r--. 1 heli heli    784 Dec  7 11:56 main.gcda  
  12. -rw-rw-r--. 1 heli heli   6632 Dec  7 11:54 main.gcno  
  13. -rw-rw-r--. 1 heli heli  27743 Dec  7 11:57 ostream.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 <strong>main.cpp.gcov</strong>
-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

生成:

  1. <strong>     main.cpp.gcov</strong>  
<strong>     main.cpp.gcov</strong>
文件,該文件記錄了每行代碼被執行的次數。

 

main.cpp.gcov文件內容如下:

  1. -:    0:Source:main.cpp  
  2.         -:    0:Graph:main.gcno  
  3.         -:    0:Data:main.gcda  
  4.         -:    0:Runs:1  
  5.         -:    0:Programs:1  
  6.         -:    1:#include <iostream>  
  7.         -:    2:using namespace std;  
  8.         1:    3:int main()  
  9.         -:    4:{  
  10.         -:    5:    int i,total;  
  11.         1:    6:    total = 0;  
  12.         -:    7:  
  13.        11:    8:    for (i=0; i<10; i++)  
  14.        10:    9:        total += i;  
  15.         -:   10:  
  16.         1:   11:    if (total != 45)  
  17.     #####:   12:        cout << "Failure!" << endl;  
  18.         -:   13:    else  
  19.         1:   14:        cout << "Success!" << endl;  
  20.         1:   15:    return 0;  
  21.         3:   16:}  
-:    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

  1. $ gcov -a main.cpp  
  2. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h'  
  3. Lines executed:0.00% of 2  
  4. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h:creating 'ios_base.h.gcov'  
  5.   
  6. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream'  
  7. Lines executed:0.00% of 11  
  8. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream:creating 'ostream.gcov'  
  9.   
  10. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/basic_ios.h'  
  11. Lines executed:0.00% of 10  
  12. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/basic_ios.h:creating 'basic_ios.h.gcov'  
  13.   
  14. File 'main.cpp'  
  15. Lines executed:88.89% of 9  
  16. main.cpp:creating 'main.cpp.gcov'  
  17.   
  18. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream'  
  19. Lines executed:100.00% of 1  
  20. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream:creating 'iostream.gcov'  
  21.   
  22. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h'  
  23. Lines executed:0.00% of 2  
  24. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h:creating 'char_traits.h.gcov'  
  25.   
  26. File '/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_facets.h'  
  27. Lines executed:0.00% of 5  
  28. /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_facets.h:creating 'locale_facets.h.gcov'  
$ 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文件內容。

  1. -:    0:Source:main.cpp  
  2.         -:    0:Graph:main.gcno  
  3.         -:    0:Data:main.gcda  
  4.         -:    0:Runs:1  
  5.         -:    0:Programs:1  
  6.         -:    1:#include <iostream>  
  7.         -:    2:using namespace std;  
  8.         1:    3:int main()  
  9.         -:    4:{  
  10.         -:    5:    int i,total;  
  11.         1:    6:    total = 0;  
  12.         -:    7:  
  13.        11:    8:    for (i=0; i<10; i++)  
  14.         1:    8-block  0  
  15.        10:    8-block  1  
  16.        11:    8-block  2  
  17.        10:    9:        total += i;  
  18.         -:   10:  
  19.         1:   11:    if (total != 45)  
  20.         1:   11-block  0  
  21.     #####:   12:        cout << "Failure!" << endl;  
  22.     
     
    $:   12-block  0  
  23.         -:   13:    else  
  24.         1:   14:        cout << "Success!" << endl;  
  25.         1:   14-block  0  
  26.         1:   15:    return 0;  
  27.         1:   15-block  0  
  28.         3:   16:}  
  29.         1:   16-block  0  
  30.         1:   16-block  1  
  31.         1:   16-block  2  
  32.         1:   16-block  3  
-:    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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章