關於使用json庫形成的內存泄露問題

上篇博文「將傳入結構體 pMtInfo 中包含的數據內容轉換成 JSON 字符串返回」的代碼雖然運行結果正確,可是形成了嚴重的內存泄露,上篇博文連接以下:http://my.oschina.net/BambooLi/blog/514946 json

用Linux內存泄露工具valgrind進行內存檢查 數組

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個塊(200malloc); 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時出現問題,與第一個紅框中的排查方法一致。

解決使用json庫後的內存泄露

根據上圖提示的錯誤,查看源碼可知,均是因爲內存沒有釋放所形成的內存泄露,對源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; }

其中加粗部分爲修改加入的內容,再對其進行內存泄露檢測:

由圖可知,內存泄露已經解決。

相關文章
相關標籤/搜索