作者:朱金灿
来源:http://blog.csdn.net/clever101
这里说的除虫是指排除bug的意思。今天排除了一个有意思的bug,其中的场景大致是这样的:现在你要统计一个文件夹下非隐藏文件的数目(包含它的子文件夹),很快你写出这样的代码:
//dirName ——文件夹路径 //nImgNum ——文件数量 bool StatFiles(std::string& dirName,int& nImgNum) { std::string tempFileFind = dirName + _T("\*") ; HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; hFind = FindFirstFile(tempFileFind.c_str(), &ffd); if (hFind != INVALID_HANDLE_VALUE) { do { tString strSub = dirName + _T("\") + ffd.cFileName; if (((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0) &&((ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)==0)) { nImgNum++; } }while (FindNextFile(hFind, &ffd) != 0); } else { return false; } tempFileFind = dirName + _T("\*"); hFind = INVALID_HANDLE_VALUE; hFind = FindFirstFile(tempFileFind.c_str(), &ffd); if (hFind != INVALID_HANDLE_VALUE) { do { if (ffd.cFileName[0] == '.') { if (ffd.cFileName[1] == ' ' || (ffd.cFileName[1] == '.' && ffd.cFileName[2] == ' ')) { continue; } } std::string strSub = dirName + _T("\") + ffd.cFileName; if (!((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0)) { StatFiles(strSub,nImgNum); } }while (FindNextFile(hFind, &ffd) != 0); } return true; }
然后拿一个文件夹来测试,嗯,测试没有问题,返回的数目也是对的。然后我们拿一个包含很多子文件夹和文件来测试,发现运行到文件数是七千多的时候函数就返回false了。开始我们比较迷惑,后来发现问题了,原来是忘记关闭文件查找句柄了,当统计达到七千多的时候已经把windows的查找句柄资源消耗尽了。我感觉这真是对WindowsAPI文件查找函数的一次压力测试。正确的代码应该是这样的:
//dirName ——文件夹路径 //nImgNum ——文件数量 bool StatFiles(std::string& dirName,int& nImgNum) { std::string tempFileFind = dirName + _T("\*") ; HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; hFind = FindFirstFile(tempFileFind.c_str(), &ffd); if (hFind != INVALID_HANDLE_VALUE) { do { tString strSub = dirName + _T("\") + ffd.cFileName; if (((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0) &&((ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)==0)) { nImgNum++; } }while (FindNextFile(hFind, &ffd) != 0); } else { return false; } FindClose(hFind); //记得关闭文件查找句柄 tempFileFind = dirName + _T("\*"); hFind = INVALID_HANDLE_VALUE; hFind = FindFirstFile(tempFileFind.c_str(), &ffd); if (hFind != INVALID_HANDLE_VALUE) { do { if (ffd.cFileName[0] == '.') { if (ffd.cFileName[1] == ' ' || (ffd.cFileName[1] == '.' && ffd.cFileName[2] == ' ')) { continue; } } std::string strSub = dirName + _T("\") + ffd.cFileName; if (!((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0)) { StatFiles(strSub,nImgNum); } }while (FindNextFile(hFind, &ffd) != 0); } FindClose(hFind); //记得关闭文件查找句柄 return true; }
如何避免这种资源泄漏的问题的发生?首先需要明确你要申请的是一种资源,在使用资源之前需要明确在哪儿释放掉资源从而避免资源泄漏。