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

 

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

posted on 2016-03-18 00:08  岚之山  阅读(187)  评论(0编辑  收藏  举报

导航