Winapi 在C+;中使用Win32 API进行递归目录遍历时堆栈溢出+;

Winapi 在C+;中使用Win32 API进行递归目录遍历时堆栈溢出+;,winapi,recursion,directory,stack,overflow,Winapi,Recursion,Directory,Stack,Overflow,我一直在试图弄明白为什么这会让我几个小时的堆栈溢出,可能是我刚刚错过的一些简单的东西,它一直在工作,直到我弄糟它,试图清理它。无论如何,一些新鲜的眼睛将不胜感激 int scan(LPSTR szPath, LPSTR pattern) { WIN32_FIND_DATA WFD; HANDLE hSearch; CHAR szFullPath [MAX_PATH+1] = ""; PVOID OldValue = NULL; if( Wow64Disa

我一直在试图弄明白为什么这会让我几个小时的堆栈溢出,可能是我刚刚错过的一些简单的东西,它一直在工作,直到我弄糟它,试图清理它。无论如何,一些新鲜的眼睛将不胜感激

int scan(LPSTR szPath, LPSTR pattern) {
    WIN32_FIND_DATA WFD;
    HANDLE hSearch;
    CHAR szFullPath [MAX_PATH+1] = "";
    PVOID OldValue = NULL;

    if( Wow64DisableWow64FsRedirection(&OldValue) ) 
    {

        PathCombine(szFullPath, szPath, "*"); 
        hSearch = FindFirstFile(szFullPath, &WFD);
        if ( hSearch != INVALID_HANDLE_VALUE ) {
            while(FindNextFile(hSearch,&WFD)) {
                if(strcmp(WFD.cFileName,"..") || strcmp(WFD.cFileName,".")){
                    FindNextFile(hSearch,&WFD);
                }
                if(WFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
                    PathCombine(szFullPath, szPath, WFD.cFileName);
                    scan(szFullPath, pattern);
                } 
            }
            FindClose(hSearch);
        }

        PathCombine(szFullPath, szPath, pattern);
        hSearch = FindFirstFile(szFullPath, &WFD);
        if( hSearch != INVALID_HANDLE_VALUE ) {
            while( FindNextFile(hSearch, &WFD) ) {
                if(!(WFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
                    PathCombine(szFullPath, szPath, WFD.cFileName);
                int index = SendDlgItemMessage(ghWnd, IDLIST, LB_ADDSTRING, 0, (LPARAM)szFullPath);

            }
        }

        FindClose(hSearch);
        if ( FALSE == Wow64RevertWow64FsRedirection(OldValue) )
        {
            return 0;
        }
    }
    return 0;
}

我认为问题在于:

    if(strcmp(WFD.cFileName,"..") || strcmp(WFD.cFileName,".")){
        FindNextFile(hSearch,&WFD);
    }
添加一个“continue”语句来修复该问题。“.”和“.”的支票是好的。问题是如果它们相邻,代码就会中断


编辑:具体来说,在这个代码块中的FindNextFile之后添加“continue”。

我认为问题在于:

    if(strcmp(WFD.cFileName,"..") || strcmp(WFD.cFileName,".")){
        FindNextFile(hSearch,&WFD);
    }
添加一个“continue”语句来修复该问题。“.”和“.”的支票是好的。问题是如果它们相邻,代码就会中断


编辑:具体来说,在这个代码块中的FindNextFile之后添加“continue”。

在您的特定情况下,您可能会意外地在枚举中包含本地目录,从而得到无限递归,然后会再次包含本地目录,等等

但即使您解决了这个问题,也会递归调用
scan
,如果您不十分小心,并且非常了解内存需求、堆栈限制等,这很容易导致堆栈崩溃

如果您解决了无限递归问题,但仍然出现堆栈溢出,通常的解决方案是实现自己的堆栈,而不是依赖递归函数调用


有关堆栈如何工作的详细信息,请参阅。

在您的特定情况下,您可能会意外地在枚举中包含本地目录,从而获得无限递归,然后该目录将再次包含本地目录,等等

但即使您解决了这个问题,也会递归调用
scan
,如果您不十分小心,并且非常了解内存需求、堆栈限制等,这很容易导致堆栈崩溃

如果您解决了无限递归问题,但仍然出现堆栈溢出,通常的解决方案是实现自己的堆栈,而不是依赖递归函数调用


有关堆栈如何工作的详细信息,请参阅。

在第一个循环中尝试此更改:

if(strcmp(WFD.cFileName,"..") || strcmp(WFD.cFileName,".")){ continue; } if(strcmp(WFD.cFileName,“…”)| | strcmp(WFD.cFileName,“.”){ 继续; }
在第一个循环中尝试此更改:

if(strcmp(WFD.cFileName,"..") || strcmp(WFD.cFileName,".")){ continue; } if(strcmp(WFD.cFileName,“…”)| | strcmp(WFD.cFileName,“.”){ 继续; }
这确实修复了无限递归,但由于某种原因,现在没有任何东西能够通过if语句,它将每个文件和目录视为其“..”或“.”将其更改为if(strcmp(WFD.cFileName,“..”)==0 | | strcmp(WFD.cFileName,“.”==0),这非常有效,不确定原因,但是谢谢。@user873294:它之所以有效,是因为strcmp不返回true/false,而是返回-1、0或1:1表示第二个字符串大于第一个字符串,0表示相等,而-1表示第一个字符串大于第二个字符串。这确实修复了无限递归,但由于某种原因,现在没有任何内容超过if语句,它将每个文件和目录视为其“..”或“.”将其更改为if(strcmp(WFD.cFileName,“..”)==0 | | | strcmp(WFD.cFileName,“.”“)==0),这非常有效,不知道为什么,但谢谢。@user873294:之所以有效,是因为
strcmp
不返回true/false,而是返回-1,0,或1:1表示第二个字符串大于第一个字符串,0表示相等,和-1表示第一个字符串大于第二个字符串。添加了此项,修复了堆栈溢出,但即使cFilename!=。。或它将继续,我已经在调试器中进行了逐步调试,不明白为什么它不会从这个if语句中排除真正的目录和文件。添加了这个,它修复了堆栈溢出,但即使cFilename!=。。或它将继续,我已经在调试程序中进行了逐步调试,但不明白为什么它不会从if语句中排除真实的目录和文件。