关于使用json库成的内存泄露问题
上篇博文“将传入结构体 pMtInfo 中包含的数据内容转换成 JSON 字符串返回”的代码虽然运行结果正确,但是造成了严重的内存泄露,上篇博文链接如下:http://my.oschina.net/BambooLi/blog/514946
用Linux内存泄露工具valgrind进行内存检查
valgrind介绍
Memcheck:这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。这也是本文将重点介绍的部分。
命令: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命令后
从上图中可以看出:
a) 堆总结(heap summary):
程序退出时还在使用的内存为332800bytes,分为200个块(即200次malloc);
总共的堆申请次数是300次,释放次数是100次,共申请内存435200bytes
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命令后

前三个红框表示内存错误的地址,最后一个方框表示错误个数;
解决使用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;
}
其中加粗部分为修改加入的内容,再对其进行内存泄露检测:
由图可知,内存泄露已经解决。