上篇博文「將傳入結構體 pMtInfo 中包含的數據內容轉換成 JSON 字符串返回」的代碼雖然運行結果正確,可是形成了嚴重的內存泄露,上篇博文連接以下:http://my.oschina.net/BambooLi/blog/514946 json
用Linux內存泄露工具valgrind進行內存檢查 數組
Memcheck:這是valgrind應用最普遍的工具,一個重量級的內存檢查器,可以發現開發中絕大多數內存錯誤使用情況,好比:使用未初始化的內存,使用已經釋放了的內存,內存訪問越界等。這也是本文將重點介紹的部分。 dom
命令:valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./test
函數
其中--leak-check=full指的是徹底檢查內存泄露,--show-reachable=yes是顯示內存泄露的地點,--trace-children=yes是跟蹤子進程。 工具
測試程序: 測試
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { printf("\n begin... \n"); int nNum = 0; while(1) { usleep(100000); char *p = (char *)malloc(1024); char *pp = (char *)malloc(2048); printf("\n p = %p, pp = %p \n", p, pp); free(p); char *ppp = (char *)malloc(1280); printf("\n ppp = %p \n", ppp); nNum++; if(nNum == 100) { break; } } printf("\n end... \n"); return 1; }執行 valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./test命令後
從上圖中能夠看出: jsonp
a) 堆總結(heap summary): ui
程序退出時還在使用的內存爲332800bytes,分爲200個塊(即200次malloc); spa
總共的堆申請次數是300次,釋放次數是100次,共申請內存435200bytes .net
b) 接下來是內存泄露點
1) main.cpp:17行分配內存100次,分配內存大小爲128000bytes,確認丟失內存爲128000bytes
2) main.cpp:14行分配內存100次,確認丟失內存204800bytes.
c) 內存泄露總結:
泄露332800bytes,在200個塊中。
使用json庫形成的內存泄露
執行valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./test命令後
前三個紅框表示內存錯誤的地址,最後一個方框表示錯誤個數;
第一紅框中的錯誤指出在test文件中的struct_to_json_n中出現問題,其問題在於調用memory.c中44行,jsonp_strdup函數是該錯誤所在的函數,還有memory.c的23行.其所在函數是jsonp_malloc。對源碼所在函數進行解讀,發如今使用json_dumps函數時調用了memory.c中的以上兩個函數,即申請了內存空間沒有釋放,故出內存泄露。
第二個紅框表示main函數中有申請內存沒有釋放的狀況,查看main函數發現對數組的內存沒有釋放
第三個紅框中的錯誤指出在test文件中的struct_to_json_n中出現問題,其問題在於調用value.c中的json_array時出現問題,與第一個紅框中的排查方法一致。
根據上圖提示的錯誤,查看源碼可知,均是因爲內存沒有釋放所形成的內存泄露,對源test.c進行修改:
#include <stdio.h> #include <string.h> #include "jansson.h" #include "upu_struct.h" #include "upu_proto_parse.h" // pMtInfo -> 傳入 mtinfo 結構的首地址 // nNum -> 傳入 mtinfo 結構的數量 // pLen -> C 結構轉換成 JSON 結構字符串後的長度 // 實現功能: // 將傳入結構體 pMtInfo 中包含的數據內容轉換成 JSON 字符串返回 char* struct_to_json_n( mtinfo *pMtInfo, int nNum, int *pLen ) { json_t *object=NULL; json_t *array=NULL; int i,size; char *result=NULL; char *CurResult=NULL; array=json_array(); for(i=0;i<nNum;++i) { object=json_object(); //結構體 pMtInfo 中包含的數據內容 const char* pMoid=mt_get_moid(&pMtInfo[i]); const char* pE164=mt_get_e164(&pMtInfo[i]); const char* pPrototype=mt_get_prototype(&pMtInfo[i]); const char* pMttype=mt_get_mttype(&pMtInfo[i]); const char* pMtstate=mt_get_mtstate(&pMtInfo[i]); const char* pMtip=mt_get_mtip(&pMtInfo[i]); const char* pNuip=mt_get_nuip(&pMtInfo[i]); const char* pUserdomain=mt_get_userdomain(&pMtInfo[i]); const char* pDevid=mt_get_devid(&pMtInfo[i]); //將結構體 pMtInfo 中包含的數據內容轉換爲json格式 json_t *pJsonMoid=json_string(pMoid); json_t *pJsonE164=json_string(pE164); json_t *pJsonPrototype=json_string(pPrototype); json_t *pJsonMttype=json_string(pMttype); json_t *pJsonMtstate=json_string(pMtstate); json_t *pJsonMtip=json_string(pMtip); json_t *pJsonNuip=json_string(pNuip); json_t *pJsonUserdomain=json_string(pUserdomain); json_t *pJsonDevid=json_string(pDevid); //將json結構的內容整合爲object json_object_set_new(object, "Moid", pJsonMoid); json_object_set_new(object, "E164", pJsonE164); json_object_set_new(object, "Prototype", pJsonPrototype); json_object_set_new(object, "Mttype", pJsonMttype); json_object_set_new(object, "Mtstate", pJsonMtstate); json_object_set_new(object, "Mtip", pJsonMtip); json_object_set_new(object, "Nuip", pJsonNuip); json_object_set_new(object, "Userdomain", pJsonUserdomain); json_object_set_new(object, "Devid", pJsonDevid); int size1=json_object_size(object); printf("[%d]:size1=%d\n",i,size1); //將本結構體數組轉化爲json格式的字符串 CurResult=json_dumps(object, JSON_PRESERVE_ORDER); printf("CurResult=%s\n",CurResult);jsonp_free(CurResult);
//將本字符串添加到json結構體數組中 json_array_insert_new(array,i,object); //json_decref(object); } size=json_array_size(array); printf("size=%d\n",size); result=json_dumps(array,JSON_PRESERVE_ORDER); //jsonp_free(result);json_decref(array);
return result; } int main() { int i = 0; int nLen = 0; int nNum = 5; char *pJsonToString=NULL; mtinfo *pMtInfoArray = NULL; pMtInfoArray = (mtinfo *)malloc( nNum * sizeof(mtinfo) ); memset( pMtInfoArray, 0, nNum * sizeof(mtinfo) ); // 經過函數 mt_set_e164 設置 E164 號 0512111885621 ~ 0512111885625 到結構 pMtInfoArray[n] 中 mt_set_e164(&pMtInfoArray[0],"0512111885621"); mt_set_e164(&pMtInfoArray[1],"0512111885622"); mt_set_e164(&pMtInfoArray[2],"0512111885623"); mt_set_e164(&pMtInfoArray[3],"0512111885624"); mt_set_e164(&pMtInfoArray[4],"0512111885625"); pJsonToString=struct_to_json_n( pMtInfoArray, nNum, &nLen ); printf("pJsonTosTring=%s\n",pJsonToString);jsonp_free(pJsonToString);
free(pMtInfoArray);
return 0; }
其中加粗部分爲修改加入的內容,再對其進行內存泄露檢測:
由圖可知,內存泄露已經解決。