您的位置:首页 > 其它

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

2016-03-18 00:08 288 查看
作者:朱金灿
来源: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;
}

如何避免这种资源泄漏的问题的发生?首先需要明确你要申请的是一种资源,在使用资源之前需要明确在哪儿释放掉资源从而避免资源泄漏。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: