作者:朱金灿

来源: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;
}

如何避免这种资源泄漏的问题的发生?首先需要明确你要申请的是一种资源,在使用资源之前需要明确在哪儿释放掉资源从而避免资源泄漏。

除虫记——有关WindowsAPI文件查找函数的一次压力测试的更多相关文章

  1. 除虫记之C#调用C函数出现的诡异错误

     作者:朱金灿 来源:http://blog.csdn.net/clever101 同事反映在在项目中使用C#程序调用我们部门编写的C++模块出现一个诡异错误:在调用A算法失败后,其它算法均不能调 ...

  2. 记在VMware虚拟机中对网站进行性能压力测试的经历

    由于本次测试,仅仅是对静态网站首页进行的测试,所以没有涉及到MySQL数据库的性能监测 服务器基本配置 webbench测试工具 Linux上一款优秀的web性能压力测试工具.webbench最多可以 ...

  3. C 语言函数手册:涵盖字符测试、字符串操作、内存管理、时间换算、数学计算、文件操作、进程管理、文件权限控制、信号处理、接口处理、环境变量、终端控制

    1. 字符测试函数 函数 说明 isascii() 判断字符是否为ASCII码字符 2. 字符串操作 函数 说明 gcvt() 将浮点型数转换为字符串(四舍五入) index() 查找字符串并返回首次 ...

  4. EPANET中读取INPUT文件的函数文件——INPUT1.C/INPUT2.C/INPUT3.C

    首先介绍下这3个文件的关系:可以说INPUT1.C的函数粒度最大,它的函数getdata()就完成了整个INPUT文件数据的读入,该函数又调用了INPUT2.C中的部分函数,INPUT2.C文件中的函 ...

  5. string.h文件中函数用法

    下面为string.h文件中函数的详细用法: strcpy函数名:strcpy功 能: 拷贝一个字符串到另一个用 法: char *strcpy(char *destin, char *source) ...

  6. 捉虫记(四)线程安全导致的HighCpu

    一个朋友QQ群里说网站启动后会cpu很高,想要帮忙看一下dump. 1.打开windbg加载dump文件后第一个命令lmf,这个命令显示加载的dll以及路径,这样子可以找个dll来帮忙加载sos,(额 ...

  7. C/C++常用头文件及函数汇总

    转自: C/C++常用头文件及函数汇总 C/C++头文件一览 C #include <assert.h> //设定插入点#include <ctype.h> //字符处理#in ...

  8. VS2005(vs2008,vs2010)使用map文件查找程序崩溃原因

    VS 2005使用map文件查找程序崩溃原因 一般程序崩溃可以通过debug,找到程序在那一行代码崩溃了,最近编一个多线程的程序,都不知道在那发生错误,多线程并发,又不好单行调试,终于找到一个比较好的 ...

  9. C语言常用的库文件(头文件、函数库)

    C语言常用的库文件(头文件.函数库) C系统提供了丰富的系统文件,称为库文件.C的库文件分为两类,一类是扩展名为".h"的文件,称为头文件,在前面的包含命令中我们已多次使用过.在& ...

随机推荐

  1. Win10+CUDA9.0+cudnn7.1安装

    CUDA下载 cudnn下载 CUDA默认安装即可. cudnn下载解压之后,将对应的文件分别拷贝到CUDA  Toolkit中即可: 对应的文件夹为: 若为默认安装,则应分别拷贝到的文件夹如下: C ...

  2. kafka之三:kafka java 生产消费程序demo示例

    kafka是吞吐量巨大的一个消息系统,它是用scala写的,和普通的消息的生产消费还有所不同,写了个demo程序供大家参考.kafka的安装请参考官方文档. 首先我们需要新建一个maven项目,然后在 ...

  3. initWithFrame 与 initWithCoder 、awakeFromNib 的方法理解笔记

    1. initWithFrame方法是什么? initWithFrame方法用来初始化并返回一个新的视图对象,根据指定的CGRect(尺寸). 当然,其他UI对象,也有initWithFrame方法, ...

  4. centos时区

    执行:cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime是将shanghai时区设置为系统时区 执行:date +%s 获取的是系统的utc时间戳 ...

  5. 线段树优化建图(cf787d, 2019Wannafly Winter Camp Day7 Div1 E)

    线段树优化建图,用于区间到区间建边时降低空间复杂度 建立两颗线段树,一颗in, 代表进入这个区间,一颗out,代表从这个区间出去 in树从父亲向儿子建边,代表宏观进入整个区间,不向下寻找 out树从儿 ...

  6. 5、overflow、hover

    一.overflow 1.属性介绍 说明: 这个属性定义溢出元素内容区的内容会如何处理.如果值为 scroll,不论是否需要,用户代理都会提供一种滚动机制.因此,有可能即使元素框中可以放下所有内容也会 ...

  7. PHP实用小程序(七)

    <? //用COOKIE保存投票人的投票记录 if($vote && !$already_voted) SetCookie("already_voted",& ...

  8. HDU3555【数位DP】

    入门...还在学习中,先贴一发大牛博客 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题目大意: 给一个数字n,范围在1~2^63-1,求1~ ...

  9. Unity3D脚本:更改脚本和类名,且不破坏现有脚本引用的方法

    Unity开发过程中,难免遇到需要修改类名(以及对应脚本名)的时候,但如果草率地在MonoDevelop里把类名直接改掉,会破坏现有场景以 及Project Assets中所有引用该脚本的链接,届时还 ...

  10. CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)

    传送门 可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的…… 首先,这题需要多项式开根和多项式求逆.多项式求逆看这里->这里,这里讲一讲多项式开根 多项式开方:已知多 ...