当前位置:C++技术网 > 资讯 > Linux下检测内存泄漏工具Valgrind的实战记录

Linux下检测内存泄漏工具Valgrind的实战记录

更新时间:2017-03-22 19:03:51浏览次数:1+次

    在《Linux下检测内存泄漏工具Valgrind的安装》中,我已经将Linux下检测内存泄漏工具Valgrind的安装方法告知大家了,当然也给了基本的使用方法。

    通过Linux下检测内存泄漏工具Valgrind检测到了4个内存问题,其实都是蛮简单的问题,只是没有注意到,所以就造成了各种内存问题。其实养成好习惯,是可以无形中提高代码质量的。

    下面把今天通过Valgrind的找到的Bug总结一下,供大家参考。

1.sprintf的使用不当问题
string GetLogFileName()
{
 char buf[100] = { 0 };
 getcwd(buf, sizeof(buf));
 sprintf(buf, "%s/log.txt",buf);
 string ret = buf;
 return ret;
}
    这段代码使用可能有两个隐患,一个是数组大小,一个是sprintf的用法不当。getcwd是Linux系统获取当前目录路径的函数。
    这会有一个问题,系统支持的目录最大长度的是多少呢?这个跟系统有关,有的是1024,有的是4096。你无法确保你的程序一定在哪个目录下运行,所以,对于路径的长度需要留心。而代码里只有100个字节,稍微深一点的目录,就好导致崩溃。
    另外,sprintf这里的用法是将buf的内容格式化到buf自己里面。如果buf空间没有用完,还留下了后续格式化的内容的空间,这个自然不是问题,但是如果buf剩余的空间不足,那么就会导致格式化的数据比buf的大小还要大,那么就会导致崩溃。
    当然,这两个错误,已经被Valgrind检测出来了。下面是检测出来的截图:
这两个错误,已经被Valgrind检测出来了


2.new和delete不匹配问题

    我使用new分配了一个数组,然后再后面释放的时候,没有加[]。自然这个会产生问题。可能有什么问题呢?分配了数组,结果按照一个变量释放了,实际上最后结果很不确定。分配整型数组假如有100字节,释放时按照整型释放了,那么这就产生了内存泄漏。
    这里就不做过多的推算了。反正这个问题是有的,大家也都懂。急切切记,尽管我们总是在说我们都知道这样的问题,但是还是会出现。在遇见new和delete是就要特别警惕,不要以为不会出现这么低级的错误。
    当然,这个错误也被Valgrind精确检测出来了。

3.数据出错时,打印内存
    我会将收到的数据的内存字节数据打印出来。而缓冲区的大小,则依据收到的数据的格式解析得到。这就有一个问题。当解析已经不正确的时候,按照格式解析出来的大小已经不正确了。如果这个数值超出了实际缓冲区的大小,就会引起内存非法访问而崩溃。开始只是习惯性的把缓冲区的内容打印出来。结果偶尔会崩溃,也会显示日志的内容为乱码。
    当然,这个错误也被Valgrind精确检测出来了。

4.在读取配置文件时,解析完数据后忘记释放分配的内存了
    比如下面这段代码:
string GetValueStr(string node_name,string file_name)
{
 string xml_file = GetConfigDir()+file_name;
 TiXmlDocument *pDoc = new TiXmlDocument(); 
 if (NULL==pDoc)return string("");
 pDoc->LoadFile(xml_file.c_str()); 
 TiXmlElement *pRootEle = pDoc->RootElement(); 
 if (NULL==pRootEle)return string("");
 TiXmlElement *pNode = NULL; 
 GetNodePointerByName(pRootEle,node_name,pNode);
 string node_text;
 if (NULL != pNode && pNode->GetText()!=NULL)
 {
 string ret = pNode->GetText();
 //delete pDoc;//忘记释放
 return ret;
 }
 //delete pDoc;//忘记释放
 return string("");
}

    这个地方忽略了pDoc的释放,然后代码里总是检测到一点内存泄漏。总是找不到,因为这部分的代码写了很久了,而且还是基础代码,所以压根就没有想到是这里的问题。Valgrind开了之后,程序在结束时就显示了内存泄漏的具体位置,然后找到了。家伙是加上释放的代码之后,内存泄漏就消失了。

    解决了上面的问题之后,代码就稳定了。在Windows中可以用VS方便的检测内存泄漏情况,而在Linux我们可以使用Valgrind来检测。检测之后,才敢说代码没有内存泄漏。