作者:朱金灿

来源: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. JavaScript 日期处理类库 moment

    可以自定义自己需要的时间格式,中文文档如下: http://momentjs.cn/ http://momentjs.cn/docs/

  2. 2019腾讯广告算法大赛 Rank23

    由于官方审核代码,代码将在2019年6月28号后开源 写在前面 这次腾讯的第三届广告算法大赛,是我第一次参加,取得了初赛与复赛均为23名的成绩,毕竟我只是初打比赛不久的小白.我想在此分享下我的基本解题 ...

  3. aidl笔记 2/5/2015

    interface Test { //测试的接口 void fun();} Stub 是一个Binderclass Stub extend Binder implements Test { publi ...

  4. 性能测试之Jmeter学习(二)

    一.Jmeter的基本操作 1.添加|移除测试元件 2.加载和保存测试元件 3.配置测试对中的测试元件 4.保存测试计划 5.运行测试计划 6.终止测试 7.错误报告 二.Jmeter体系结构 注释: ...

  5. jQuery.validator.addMethod方法的使用

    该方法有三个api接口参数,name,method,messages addMethod(name,method,message)方法 参数 name 是添加的方法的名字. 参数 method 是一个 ...

  6. crontab计划任务监控nginx服务器

    #!/bin/bash ps axu |grep 'nginx' |grep -v 'grep' &>/dev/null ] then echo "准备重启nginx....& ...

  7. AWS AutoScaling的一个ScaleDown策略问题以及解决方法

    此文已由作者袁欢授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1. AWS AutoScaling简介 AutoScaling是AWS的一个重要服务,用来弹性的自动创建(S ...

  8. mysql order by是怎么工作的?

    假设我们要查询一个市民表中城市=杭州的所有人的名字,并且按照名字排序 CREATE TABLE `t` ( `id` ) NOT NULL, `city` ) NOT NULL, `name` ) N ...

  9. hdoj 1588 学好线代与数学

    按部就班,超级简单,虽然不是一次过的...错在那个long long数据问题还是要注意..也不知道要怎么注意:还是说题目吧... 思路看main函数 其他函数功能也是非常有用!代码比较丑...见谅 # ...

  10. jzoj5986. 【WC2019模拟2019.1.4】立体几何题 (权值线段树)

    传送门 题面 题解 不难看出每个点的大小为行列限制中较小的那一个(因为数据保证有解) 对于行的每个限制,能取到的个数是列里限制大于等于它的数的个数,同理,对于列是行里大于它的个数(这里没有等于,为了避 ...