1

I have a bit of code that is working except it is causing a stack overflow. I know the issue is caused because of recursion but I am not sure what I can do to stop it in this scenario.

The Code:

void FindFilesRecursively(LPCTSTR lpFolder) {
    TCHAR szFullPattern[MAX_PATH];
    WIN32_FIND_DATA FindFileData;
    HANDLE hFindFile;

    PathCombine(szFullPattern, lpFolder, (L"*"));
    hFindFile = FindFirstFile(szFullPattern, &FindFileData);
    if (wcscmp(FindFileData.cFileName, L".") == 0){
        FindNextFile(hFindFile, &FindFileData);
        if (wcscmp(FindFileData.cFileName, L"..") == 0) {
            FindNextFile(hFindFile, &FindFileData);
        }
    }
    if (hFindFile != INVALID_HANDLE_VALUE) {
        do {
            if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                // found a subdirectory; recurse into it
                PathCombine(szFullPattern, lpFolder, FindFileData.cFileName);
                printf("FOLDER: %S\n", szFullPattern);
                FindFilesRecursively(szFullPattern);
            }
            printf("FILE: %S\n", FindFileData.cFileName);
        } while (FindNextFile(hFindFile, &FindFileData));
        FindClose(hFindFile);
    }
    printf("END\n");
}

Basically all it does it takes a folder/file path as argument and then it will print the name if it is a folder, or it will go recursively through the path and print everything. My debugger is hitting stack overflow at about 53 calls to this function. I am not sure where/how I should terminate a call to this function so that it doesn't cause the stack overflow.

9
  • 3
    Fyi, the checks fro '.' and '..' and an subsequent ignoring of said-same should be part of the loop; not assumed to optionally be the first (or first two) entries. As soon as the latter assumption fails, the entire loop will recurse indefinitely. Commented Aug 9, 2021 at 16:44
  • 2
    Take action on the value of hFindFile immediately: you are executing code based on the supposed data in FindFileData in between. Commented Aug 9, 2021 at 16:47
  • What is MAX_PATH Commented Aug 9, 2021 at 16:50
  • 260, its not coming close to that. Commented Aug 9, 2021 at 16:52
  • 1
    "If the function fails, the return value is zero and the contents of lpFindFileData are indeterminate." I suggest you have a single loop, which ignores "." and "..". Commented Aug 9, 2021 at 17:03

1 Answer 1

2

When your code hits empty directory, it will backtrack to parent directory:

if (wcscmp(FindFileData.cFileName, L"..") == 0) {
        FindNextFile(hFindFile, &FindFileData);
    }
}
if (hFindFile != INVALID_HANDLE_VALUE) {

FindNextFile returns zero if no more entries, but your code doesn't check for it. Since hFindFile is not INVALID_HANDLE_VALUE, your code happily processes cached ".." as next found entry, but it will redirect to parent folder (and eventually produce SO). Here is the fixed code:

    void FindFilesRecursively(LPCTSTR lpFolder) {
    TCHAR szFullPattern[MAX_PATH];
    WIN32_FIND_DATA FindFileData;
    HANDLE hFindFile;

    PathCombine(szFullPattern, lpFolder, (L"*"));
    hFindFile = FindFirstFile(szFullPattern, &FindFileData);
    if (hFindFile != INVALID_HANDLE_VALUE) {
        do {
            if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && 
                wcscmp(FindFileData.cFileName, L".") != 0 && 
                wcscmp(FindFileData.cFileName, L"..") != 0) {
                // found a subdirectory, and it's neither .. nor ..; recurse into it
                PathCombine(szFullPattern, lpFolder, FindFileData.cFileName);
                printf("FOLDER: %S\n", szFullPattern);
                FindFilesRecursively(szFullPattern);
            }
            printf("FILE: %S\n", FindFileData.cFileName);
        } while (FindNextFile(hFindFile, &FindFileData));
        FindClose(hFindFile);
    }
    printf("END\n");
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.