Winapi FindNextFileA返回6(错误\u无效\u句柄)
有一个递归查找文件夹中所有文件的函数(存储在logPath文件夹名称末尾有'\')。它用于64位控制台应用程序(在MSVC 2008中编译),并在Win764位操作系统上运行 当我运行类似“program.exe folder_to_find”的应用程序时,它运行得很好 当我运行类似“program.exe folder_to_find>>result.txt”的应用程序时,它会失败,返回错误6(错误\u无效\u句柄),返回FindNextFileA(即使没有对大文件夹的递归调用)。例如,它可以找到文件夹中的前150个文件,而不是现有的240个文件Winapi FindNextFileA返回6(错误\u无效\u句柄),winapi,visual-c++,console-application,Winapi,Visual C++,Console Application,有一个递归查找文件夹中所有文件的函数(存储在logPath文件夹名称末尾有'\')。它用于64位控制台应用程序(在MSVC 2008中编译),并在Win764位操作系统上运行 当我运行类似“program.exe folder_to_find”的应用程序时,它运行得很好 当我运行类似“program.exe folder_to_find>>result.txt”的应用程序时,它会失败,返回错误6(错误\u无效\u句柄),返回FindNextFileA(即使没有对大文件夹的递归调用)。例如,它可以
void FindFiles(const std::string &logPath, FileList& fileList)
{
WIN32_FIND_DATAA fd;
HANDLE f = FindFirstFileA((logPath + "*").c_str(), &fd);
if (f == INVALID_HANDLE_VALUE)
{
printf("No files found at %s - %d\n", logPath.c_str(), GetLastError());
return;
}
FileList dirList;
do
{
if (strcmp(fd.cFileName, ".") == 0)
continue;
if (strcmp(fd.cFileName, "..") == 0)
continue;
std::string path = logPath + fd.cFileName;
printf("Processing %s\n", path.c_str());
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
dirList.push_back(path);
else
fileList.push_back(path);
}
while (FindNextFileA(f, &fd) != 0);
DWORD err = GetLastError();
if (err != ERROR_NO_MORE_FILES)
{
printf("Unexpected error in FindNextFileA(%s): %d\n", logPath.c_str(), err);
fflush(stdout);
abort();
}
FindClose(f);
//for(FileList::const_iterator it = dirList.begin(); it != dirList.end(); ++it)
// FindFiles(*it, fileList);
}
我无法说明为什么
FindFirstFileA()
在使用控制台重定向时会返回特定的错误代码(您没有显示如何将结果输出到控制台),但代码中存在一些小错误(最明显的是,您没有对FindFirstFileA()进行充分的错误处理)
,而不是通过递归调用FindFiles()
将\
追加到目录路径的末尾
请尝试以下方法:
void FindFiles(const std::string &logPath, FileList& fileList)
{
WIN32_FIND_DATAA fd;
DWORD err;
std::string sLogPath(logPath);
if (sLogPath.length() > 0)
{
if (sLogPath[sLogPath.length()-1] != '\\')
sLogPath += '\\';
}
HANDLE f = FindFirstFileA((sLogPath + "*").c_str(), &fd);
if (f == INVALID_HANDLE_VALUE)
{
err = GetLastError();
if (err != ERROR_FILE_NOT_FOUND)
{
printf("Unexpected error in FindFirstFileA(%s): %d\n", sLogPath.c_str(), err);
fflush(stdout);
abort();
}
printf("No files found at %s\n", sLogPath.c_str());
return;
}
FileList dirList;
do
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if ((strcmp(fd.cFileName, ".") != 0) && (strcmp(fd.cFileName, "..") != 0))
{
std::string path = sLogPath + fd.cFileName;
printf("Processing dir %s\n", sLogPath.c_str());
dirList.push_back(path);
}
}
else
{
std::string path = sLogPath + fd.cFileName;
printf("Processing file %s\n", path.c_str());
fileList.push_back(path);
}
}
while (FindNextFileA(f, &fd));
err = GetLastError();
FindClose(f);
if (err != ERROR_NO_MORE_FILES)
{
printf("Unexpected error in FindNextFileA(%s): %d\n", sLogPath.c_str(), err);
fflush(stdout);
abort();
}
//for(FileList::const_iterator it = dirList.begin(); it != dirList.end(); ++it)
// FindFiles(*it, fileList);
}
有一个
boost::thread t
,我通过handle h=t存储它的句柄。native\u handle()
有一个调用CloseHandle(h)
稍后关闭它
我忘了,然后boost::~thread()
destructor也关闭了它的句柄
在我复制线程句柄之后handleh=NULL代码>
::DuplicateHandle(…,t.native_handle(),&h…)
关闭前-出现问题…结果文件是在您正在搜索的目录中创建的(还是在您正在搜索的目录的子目录中)?如果是这样,在搜索目录时打开(并更改)一个文件可能会导致问题。您可能需要进行一些实验,以进一步了解导致此问题的条件。不,正在目标目录外创建结果文件。没有打开任何文件,至少是程序打开的。printf?!为什么不使用cout
?然后你就可以避免那些讨厌的c_str()
调用了。您还必须在关联的API调用失败后立即调用GetLastError()
。在Q中的代码中没有这样做。printf
只是一个坏习惯,对不起GetLastError
,如我所见,在FindNextFileA
调用之后立即被调用。这一个很好,但FindFirstFileA之后的一个不好。当然logPath.c_str()
不会有问题,但是在调用GetLastError
时要非常精确,这是一个好习惯。这段代码在第122次细分后会导致相同的错误-使用控制台重定向时FindNextFileA(1):6中出现意外错误仔细查看该错误消息。它说logPath
是“1”
,这不是有效的路径。这应该是你第一次发现问题的线索FindNextFileA()
抱怨f
不是有效的句柄。因此,这里显示的代码之外的东西正在破坏内存,而您的两个变量都是这种破坏的受害者。文件列表
声明为什么?它是动态增长的还是有限制的?我已经将您的代码logPath+“*”
改为logPath+“\\*”
运行<代码>文件列表
声明为typedef std::vector文件列表代码>。我依赖STL.)没有外部代码-除了此代码和main
之外,我已经对所有代码进行了注释,在这里我将argv[1]
传递给FindFiles
。如果将过滤器更改为使用+“\\*”
,则在递归循环中调用FindFiles()
时必须删除+“\\”
,您必须确保在argv[1]
值的末尾不包含'\'
。我建议让FindFiles()
将logPath
赋值给一个局部变量,如果缺少,则在其末尾追加“\\”
,然后到处使用该变量,而不是直接使用logPath
。但这仍然不能解释为什么发生故障时,logPath
是“1”
,而f
是无效的。这仍然表明内存已损坏。为什么要手动关闭线程句柄?为什么不让boost::thread
为您处理这个问题呢?这段代码是另一个应用程序测试的一部分,其中是关闭进程句柄的CloseHandle
,线程用来模拟这个进程的行为。