除虫记——有关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;
}

 

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

转载于:https://www.cnblogs.com/lanzhi/p/6469927.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值