1.C/C++統計內存泄漏問題
對於查找代碼中存在的內存泄漏問題,我們可以使用valgrind工具來檢查是否存在內存泄漏問題。比如下面的程序,在堆空間分配20個字節後,程序結束以前並沒有釋放掉這部分內存。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
char * output = (char *)malloc(sizeof(char) * 20);
char * src = "check memory";
if(!output) {
fprintf(stderr, "alloc memory failed.");
}
memcpy(output, src, strlen(src));
printf("Output:%s\n",output);
return 0;
}
在使用下面指令編譯生成可執行文件運行後,代碼中並沒有出現任何異常。
gcc main.c -o main
yongli.tong@tj06009pcu:~/code/slog/test$ ./main
Output:check memory
我們可以使用valgrind運行後,能夠看到如下問題,從輸出來看,提示有20bytes的內存泄漏,但是提示如果查看完整信息,需要增加--leak-check=full的字段。
yongli.tong@tj06009pcu:~/code/slog/test$ valgrind ./main
==14314== LEAK SUMMARY:
==14314== definitely lost: 20 bytes in 1 blocks
==14314== indirectly lost: 0 bytes in 0 blocks
==14314== possibly lost: 0 bytes in 0 blocks
==14314== still reachable: 0 bytes in 0 blocks
==14314== suppressed: 0 bytes in 0 blocks
==14314== Rerun with --leak-check=full to see details of leaked memory
接下來,我們在valgrind命令中增加--leak-check=full字段,最終,可以看到內存泄漏發生的位置。
yongli.tong@tj06009pcu:~/code/slog/test$ valgrind --leak-check=full ./main
==14365== 20 bytes in 1 blocks are definitely lost in loss record 1 of 1
==14365== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14365== by 0x4006AA: main (in /home/yongli.tong/code/slog/test/main)
2.統計代碼覆蓋率的方法
我們在開發階段,需要統計代碼覆蓋率,一方面爲了在單元測試中能夠發現代碼中的邏輯漏洞;另一方面,也將測試前移,提前發現代碼中的問題;最後,對於統計代碼覆蓋率還可以發現代碼中是否存在無效的代碼。對於工具,我這邊使用的是gcov。
在開始之前,我們需要先在系統中安裝該工具,命令如下:
sudo apt-get install ggcov
下面,我編寫了兩個文件,分別爲main.c(充當測試用例的作用):
#include <stdio.h>
#include <assert.h>
#include "test.h"
#define START_NEW_TEST(test_num) \
fprintf(stderr, "Test %d...", (++test_num));
#define END_TEST(test_num) \
fprintf(stderr, "pass.\n");
int main(int argc, char** argv) {
int test_num = 0;
START_NEW_TEST(test_num);
assert(test_case(2)==TRUE);
END_TEST(test_num);
START_NEW_TEST(test_num);
assert(test_case(-1)==TRUE);
END_TEST(test_num);
START_NEW_TEST(test_num);
assert(test_case(0)==FALSE);
END_TEST(test_num);
return 0;
}
test.c:充當被測試文件,統計裏面test_case函數的覆蓋率。
#include "test.h"
int test_case(int para) {
if(para != 0) {
return TRUE;
} else {
return FALSE;
}
}
覆蓋率,可以在gcc中加入--coverage字段,編譯的全部命令如下:
2087 gcc -c main.c -o main-gcov.o
2088 gcc --coverage -c test.c -o test-gcov.o
2089 gcc -o main-gcov --coverage main-gcov.o test-gcov.o
2091 ./main-gcov
2092 gcov -o test-gcov.o test.c
最終運行gcov結果後,會生成統計覆蓋率的數據(100%)。
yongli.tong@tj06009pcu:~/code/slog/test$ gcov -o test-gcov.o test.c
File 'test.c'
Lines executed:100.00% of 4
test.c:creating 'test.c.gcov'
然後,可以根據.gcno .gcda文件生成圖形化報告,命令如下:
yongli.tong@tj06009pcu:~/code/slog/test$ lcov -c -d . -o test_gcov.info
yongli.tong@tj06009pcu:~/code/slog/test$ genhtml -o 111 test_gcov.info
上面的兩條命令執行以後,可以在工程目錄(我這裏是~/code/slog/test)中生成111目錄,裏面會有html文件。
最後,說明在執行gcov時,我這邊出現瞭如下的一個錯誤,主要是/usr/bin/gcov連接的版本不匹配。解決方案是,修改一下/usr/bin/gcov對應的軟連接再執行gcov就沒有這個問題了。
.gcno:version '404*', prefer '408*'
yongli.tong@tj06009pcu:~/code/slog/test$ ls /usr/bin/gcov*
/usr/bin/gcov /usr/bin/gcov-4.4 /usr/bin/gcov-4.6 /usr/bin/gcov-4.8
yongli.tong@tj06009pcu:~/code/slog/test$ sudo ln -sf /usr/bin/gcov-4.4 /usr/bin/gcov
yongli.tong@tj06009pcu:~/code/slog/test$ ls -al /usr/bin/gcov
lrwxrwxrwx 1 root root 17 Mar 17 18:04 /usr/bin/gcov -> /usr/bin/gcov-4.4