valgrind --tool=memcheck --leak-check=full ./httptestios
valgrind --tool=memcheck --leak-check=full --track-origins=yes --show-reachable=yes ./httptestc++
用法: valgrind [options] prog-and-args [options]: 經常使用選項,適用於全部Valgrind工具編程
LOG信息輸出數組
適用於Memcheck工具的相關選項:安全
// Automatic objects are not destroyed as a result of calling exit() #include <iostream> #include <chrono> #include <thread> #include <mutex> #include <pthread.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <error.h> #include <vector> #include <algorithm> #include <sstream> #include <string> int fail(const std::string str) { std::cerr<< str << std::endl; exit(1); } const std::string usage() { std::string a = "a"; return a; } int main() { fail(usage()); return 0; }
$ g++ -std=c++0x main.cpp -o xmain多線程
$ valgrind ./xmainsocket
==18699== definitely lost: 0 bytes in 0 blocks
==18699== indirectly lost: 0 bytes in 0 blocks
==18699== possibly lost: 26 bytes in 1 blocks
==18699== still reachable: 0 bytes in 0 blocks
==18699== suppressed: 0 bytes in 0 blocks
==18699== Rerun with --leak-check=full to see details of leaked memoryide
什麼是coredump?函數
一般狀況下coredmp包含了程序運行時的內存,寄存器狀態,堆棧指針,內存管理信息等。能夠理解爲把程序工做的當前狀態存儲成一個文件。許多程序和操做系統出錯時會自動生成一個core文件。工具
造成程序coredump的緣由不少,這裏根據以往的經驗總結一下:
1 內存訪問越界
a) 因爲使用錯誤的下標,致使數組訪問越界
b) 搜索字符串時,依靠字符串結束符來判斷字符串是否結束,可是字符串沒有正常的使用結束符
c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操做函數,將目標字符串讀/寫爆。應該使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函數防止讀寫越界。
2 多線程程序使用了線程不安全的函數。
應該使用下面這些可重入的函數,尤爲注意紅色標示出來的函數,它們很容易被用錯:
asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n) ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c) getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c) fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c) getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3) getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n) nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3) getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c)strtok_r(3c) getgrent_r(3c) getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c) getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)
3 多線程讀寫的數據未加鎖保護。
對於會被多個線程同時訪問的全局數據,應該注意加鎖保護,不然很容易形成core dump
4 非法指針
a) 使用空指針
b) 隨意使用指針轉換。一個指向一段內存的指針,除非肯定這段內存原先就分配爲某種結構或類型,或者這種結構或類型的數組,不然不要將它轉換爲這種結構或類型 的指針,而應該將這段內存拷貝到一個這種結構或類型中,再訪問這個結構或類型。這是由於若是這段內存的開始地址不是按照這種結構或類型對齊的,那麼訪問它 時就很容易由於bus error而core dump. 總線錯誤(bus error)一般是指針強制轉換,致使CPU讀取數據違反了必定的總線規則。《c專家編程》
#include <stdlib.h> #include <stdio.h> #if defined(__GNUC__) # if defined(__i386__) /* Enable Alignment Checking on x86 */ __asm__("pushf\norl $0x40000,(%esp)\npopf"); # elif defined(__x86_64__) /* Enable Alignment Checking on x86_64 */ __asm__("pushf\norl $0x40000,(%rsp)\npopf"); # endif #endif
int main() {
union{ char a[10]; int i; }u;
int *p =(int*)&(u.a[1]); *p =17; printf("%d\n", *p); } |
緣由是:
x86體系結構會把地址對齊以後,訪問兩次,而後把第一次的尾巴和第二次的頭拼起來。
若是不是x86,那種體系結構下的機器不願自動幹這活,就會產生core。
若是在代碼中將對齊檢查功能打開,運行後能顯示bus error。
5 堆棧溢出
不要使用大的局部變量(由於局部變量都分配在棧上),這樣容易形成堆棧溢出,破壞系統的棧和堆結構,致使出現莫名其妙的錯誤。
在一般的編程開發與應用中,寬泛地講,內存泄漏是分配了內存可是沒有在程序終止前釋放。嚴格且更有實際意義地講,內存泄漏是分配了某塊內存可是隨後程序再也不擁有指向該內存的任何指針了。內存泄露檢測工具valgrind使用的即是嚴格意義上內存泄露檢測原則。下文若是沒有特殊說明,一律指嚴格定義的內存泄露。內存泄露潛在地引發顯著的堆消耗,特別對於長久持續運行的程序。關於「still reachable」類型的Valgrind內存泄露檢測報告僅適用於寬泛定義的內存泄露。假如使用valgrind工具檢測到了程序出現「still reachable」,說明程序沒有釋放這種類型的內存塊,可是並不表明這些內存塊永遠的丟失了,不能被釋放了,由於程序依然擁有指向這些內存塊的指針。通常而言,它們不會引發嚴格意義上的內存泄露形成的問題(潛在的堆空間消耗以至無內存可用),因此不用擔憂這些「still reachable」內存塊。這是由於這些內存塊一般申請一次,在進程的整個生命週期內一直保持着引用。固然,你也能夠全程確保你的程序釋放掉全部分配的內存。由於OS會在進程終止後回收進程的全部內存,所以這樣作的意義不大。相反,若是存在真正的內存泄露,也許僅僅引發進程消耗的內存多於所需,也許程序運行時間足夠長,引發一個進程耗盡內存。