除虫记——有关WindowsAPI文件查找函数的一次压力测试
2016-03-18 00:08
288 查看
作者:朱金灿
来源:http://blog.csdn.net/clever101
这里说的除虫是指排除bug的意思。今天排除了一个有意思的bug,其中的场景大致是这样的:现在你要统计一个文件夹下非隐藏文件的数目(包含它的子文件夹),很快你写出这样的代码:
然后拿一个文件夹来测试,嗯,测试没有问题,返回的数目也是对的。然后我们拿一个包含很多子文件夹和文件来测试,发现运行到文件数是七千多的时候函数就返回false了。开始我们比较迷惑,后来发现问题了,原来是忘记关闭文件查找句柄了,当统计达到七千多的时候已经把windows的查找句柄资源消耗尽了。我感觉这真是对WindowsAPI文件查找函数的一次压力测试。正确的代码应该是这样的:
如何避免这种资源泄漏的问题的发生?首先需要明确你要申请的是一种资源,在使用资源之前需要明确在哪儿释放掉资源从而避免资源泄漏。
来源: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] == '\0' || (ffd.cFileName[1] == '.' && ffd.cFileName[2] == '\0')) { 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] == '\0' || (ffd.cFileName[1] == '.' && ffd.cFileName[2] == '\0')) { 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; }
如何避免这种资源泄漏的问题的发生?首先需要明确你要申请的是一种资源,在使用资源之前需要明确在哪儿释放掉资源从而避免资源泄漏。
相关文章推荐
- HRBUST 1326 循环找父节点神术
- emacs简单入门
- [算法]折半查找
- 无线节点的空中唤醒
- 数据结构(16)顺序栈的表示和算法表示
- Servlet上传
- Centos
- 虚函数与虚函数表
- 进程自我保护 适用于WIN7 X64
- 开启新的activity获取它的返回值
- android中根据资源文件的名称获得资源文件的Id
- QT 4.2.2的安装(安装完还要再编译,注意设置Windows Path)
- 解析xml
- POJ2299 Ultra-QuickSort(线段树)
- IE8及以下不识别H5标签
- 深入了解asp.net框架。生命周期以及事件处理机制
- Java利用System.getProperty("file.encoding")获取编码分析
- 新工作新的征途
- Myeclipse
- 【数据结构与算法】十一 最大公约数