Winapi FindNextFileA返回6(错误\u无效\u句柄)

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(即使没有对大文件夹的递归调用)。例如,它可以

有一个递归查找文件夹中所有文件的函数(存储在logPath文件夹名称末尾有'\')。它用于64位控制台应用程序(在MSVC 2008中编译),并在Win764位操作系统上运行

当我运行类似“program.exe folder_to_find”的应用程序时,它运行得很好

当我运行类似“program.exe folder_to_find>>result.txt”的应用程序时,它会失败,返回错误6(错误\u无效\u句柄),返回FindNextFileA(即使没有对大文件夹的递归调用)。例如,它可以找到文件夹中的前150个文件,而不是现有的240个文件

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
,线程用来模拟这个进程的行为。