0

I am trying to write a script to recursivly scan a disk and return the total numbers of directories, files and also display the largest file found. I know that there is much information to find on StackOverflow or on the web, but all the examples I found so far seem to have issues with really scan a disk recursivly. Below script uses the FindFile and FindNextFile functions to scan for files. If the file atribute returns that the the function found a directory it writes the name into a list to be searched later. After the current directory has been searched the script takes the first item (being a directory to be scanned) of the list, removes that item from the list and scans this directory.

My problem is that after scanning a few hundred directories and subdirectories the program end with an error

Unhandled exception at ..... (ntdll.dll) in File Lister 6.0.exe: .....: Stack overflow

or

Unhandled exception at ..... (ntdll.dll) in File Lister 6.0.exe: ......: Access violation writing location 0x00f30fe8.

But the then scanned directory is never the same.

I have been trying to solves this issue but can not find a clear reason for it. Therefore I would much appreciate if someone could help

Below is my code. I know it's looking very novice, my apologises for that

    #include <windows.h>
    #include <iostream>
    #include <fstream>
    #include <conio.h>
    #include <ctype.h>
    #include <string>
    #include <string.h>
    #include <stdio.h>
    #include <direct.h>
    #include <list>

    using namespace std;


    list <string> myList;
    std::list<string>::iterator it;

       int siZe;
       int siZekB;
       bool  bSearchSubdirectories=true;
       HANDLE handle;
       LPCTSTR strPattern;
       std::string temp;
       std::string temp1;
       std::string temp2;
       std::string temp3;
       WIN32_FIND_DATA search_data;
       int DIRPlace;
       int MaxDir=400000000;

       int telDIR=1;
       int telFILES=1;
       double LargestFile=0;
       string LargestFileName;
       string SDir;


    std::string string_to_hex(const std::string& input)
    {
        static const char* const lut = "0123456789ABCDEF";
        size_t len = input.length();

        std::string output;
        output.reserve(2 * len);
        for (size_t i = 0; i < len; ++i)
        {
            const unsigned char c = input[i];
            output.push_back(lut[c >> 4]);
            output.push_back(lut[c & 15]);
        }
        return output;
    }



    int SearchDirectory(string FileSearch ,string refvecFiles,
                        bool bSearchSubdirectories)
    {  

       WIN32_FIND_DATA search_data;
       memset(&search_data, 0, sizeof(WIN32_FIND_DATA));
       HANDLE handle = FindFirstFile((refvecFiles+FileSearch).c_str(), &search_data);  
       temp = refvecFiles;
       while(handle != INVALID_HANDLE_VALUE)   {

               do{
                   if (search_data.cFileName[0]!='.'){  
                           temp2=search_data.dwFileAttributes;
                           temp3=string_to_hex(temp2);
                           DIRPlace=strlen(temp3.c_str())-1;
                       switch (temp3[DIRPlace-1])
                       {
                          case '1':    //Directory
                               temp = refvecFiles;
                               temp1=search_data.cFileName;
                               temp2=search_data.dwFileAttributes;
                               myList.push_back(temp+temp1);
                               telDIR++;
                               break; 
                         default:   //Other types (Files etc)
                               siZe=(search_data.nFileSizeHigh * (MAXDWORD+1)) + search_data.nFileSizeLow;
                               siZekB=((search_data.nFileSizeHigh * (MAXDWORD+1)) + search_data.nFileSizeLow)/1024;
                               temp = refvecFiles;
                               temp1=search_data.cFileName;
                               temp2=search_data.dwFileAttributes;
                               if (siZekB>LargestFile){
                                  LargestFile=siZekB;
                                  LargestFileName=temp.substr(0, temp.size()) + "\\" + temp1;
                               }
                               telFILES++;
                               break;
                       }
                   }  
                }while      (FindNextFile(handle, &search_data) != FALSE && telDIR<MaxDir);
                                  string line,SearD, LineFiller,FrontString, BackString;


                      it=myList.begin();
                        SearD=*it+"\\\\";
                        myList.remove(*it);
                      if (SearD.length()>60)
                      {
                          FrontString=SearD.substr(0,10);
                          BackString=SearD.substr(SearD.length()-44);
                          LineFiller="......";
                          FrontString=FrontString+LineFiller+BackString;
                      }else{
                        FrontString=SearD;
                      }
                      cout<<"Exploring:                                                              "<<"\r";
                      cout<<"Exploring: "<<FrontString<<"\r\r";
                      SearchDirectory("\\*",SearD, false);     
       }
       FindClose(handle);
       return 0;

    }





    int main(int argc, char* argv[])
    {   
        std::cout<< "Enter directory to be searched: ";
        getline(cin,SDir);
        std::cout<< "\n";
        try{
        SearchDirectory("\\*",SDir, false);
        }catch (int e)
  {
    cout << "An exception occurred. Exception Nr. " << e << '\n';
  }
                std::cout<< "\n"<<"\n";
        std::cout<<"Directories found: "<< telDIR<< "\n";
        std::cout<<"Files found: "<< telFILES<< "\n"; 
        std::cout<<"Largest File: "<<LargestFileName << " ("<< LargestFile << " kB)"<<"\n";     
        std::cout<<"press any key";
        getch();       
    }

EDIT: Below is a snapshot from the debugger Call Stack

>   File Lister 6.0.exe!std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}, const char * _Val=0x000d51c8)  Line 791 + 0x20 bytes   C++
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\numeric\\interval\\", bool bSearchSubdirectories=false)  Line 110 + 0x16 bytes   C++
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\numeric\\conversion\\", bool bSearchSubdirectories=false)  Line 113  C++
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multi_index\\detail\\", bool bSearchSubdirectories=false)  Line 113  C++
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multiprecision\\traits\\", bool bSearchSubdirectories=false)  Line 113   C++
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multiprecision\\detail\\", bool bSearchSubdirectories=false)  Line 113   C++
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multiprecision\\cpp_int\\", bool bSearchSubdirectories=false)  Line 113  C++
    File Lister 6.0.exe!SearchDirectory(std::basic_string<char,std::char_traits<char>,std::allocator<char> > FileSearch="\*", std::basic_string<char,std::char_traits<char>,std::allocator<char> > refvecFiles="c:\\boost\\multiprecision\\concepts\\", bool bSearchSubdirectories=false)  Line 113 C++

The debugger stops in ostream at

if (_State == ios_base::goodbit
    && _Ostr.rdbuf()->sputn(_Val, _Count) != _Count)
    _State |= ios_base::badbit;
HB1963
  • 107
  • 1
  • 2
  • 11
  • People keep adding the C++ tag to your C++11 questions. Please take the hint! – Lightness Races in Orbit Dec 23 '15 at 20:07
  • If you get a crash the first thing you should do is to run your program in a debugger, and let the debugger catch the crash in action. That will tell you *where* the crash happened, and you will be able to examine the function call stack and go up it to your code (if the debugger doesn't stop in your code already), and then you can examine the values of all variables. At the very least you should edit your question to show us the location *in your code* of the crash, and preferably the values of the involved variables. – Some programmer dude Dec 23 '15 at 20:08
  • Possible duplicate of [How do you iterate through every file/directory recursively in standard C++?](http://stackoverflow.com/questions/67273/how-do-you-iterate-through-every-file-directory-recursively-in-standard-c) – Pavel Pája Halbich Dec 23 '15 at 20:11

2 Answers2

1

From the looks of it, you have implemented an infinite recursion which just won't run to infinite but rather only until you run out resources. Notably, at the bottom of SearchDirectory() you call SearchDirectory() with the same parameters as when you innitially call it. You need to make sure the recursion stops eventually.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

OK, I found the answer. It all had to do with infinitive recursion. If anyone is interested, I have rewritten the code. It scan a 650GB harddrive (over 750k files) within 100 seconds and returns some nice data:

    #include <windows.h>
    #include <iostream>
    #include <fstream>
    #include <conio.h>
    #include <ctype.h>
    #include <string>
    #include <string.h>
    #include <stdio.h>
    #include <direct.h>
    #include <list>
    #include <vector>
    #include <ctime>
    #include <iomanip>

using namespace std;

    vector <string> myList;

       int siZe;
       int siZekB;
       bool  bSearchSubdirectories=true;
       HANDLE handle;
       LPCTSTR strPattern;
       std::string temp;
       std::string temp1;
       std::string temp2;
       std::string temp3;
       WIN32_FIND_DATA search_data;
       int DIRPlace;

       int telDIR=0;
       int telFILES=0;
       int telFILESHidden=0;
       double LargestFile=0;
       double LargestFileHidden=0;
       double TotalUsed=0;
       double TotalUsedHidden=0;
       string LargestFileName;
       string LargestFileNameHidden;
       string SDir;
       string line,SearD, LineFiller,FrontString, BackString;
       int SearchDirectory(string FileSearch ,string refvecFiles,
                        bool bSearchSubdirectories);


int main(int argc, char* argv[])
    {   
        system("mode CON: COLS=140 LINES=22");
        std::cout<< "Enter directory to be explored: ";
        getline(cin,SDir);
        std::cout<< "\n";

  clock_t begin = clock();



        SearchDirectory("\\*.*",SDir, false);

        while (!myList.empty()){

            SearD=myList.back();
            myList.pop_back();

            SearchDirectory("\\*.*",SearD.c_str(), false);
        }


        clock_t end = clock();
        double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;

        std::cout<< "\n"<<"\n";
        system("cls");
        std::cout<<"Directory explored in      : "<<elapsed_secs<<" seconds\n";
        std::cout<<"Explored (sub)directories  : "<< telDIR<< "\n";
        std::cout<<"Unexplored directories     : "<<myList.size()<<"\n\n";
        std::cout<<setprecision (2)<<fixed<<"Files found                : "<< telFILES<< " using "<<TotalUsed<<" kB storage\n"; 
        std::cout<<setprecision (2)<<fixed<<"Largest File               : "<<LargestFileName << " ("<< LargestFile << " kB)"<<"\n\n";

        std::cout<<setprecision (2)<<fixed<<"Hidden Files found         : "<< telFILESHidden<< " using "<<TotalUsedHidden<<" kB storage\n"; 
        std::cout<<setprecision (2)<<fixed<<"Largest Hidden File        : "<<LargestFileNameHidden << " ("<< LargestFileHidden << " kB)"<<"\n";

        std::cout<<"press any key";
        getch();       
    }


    int SearchDirectory(string FileSearch ,string refvecFiles,
                        bool bSearchSubdirectories)
    {  

       WIN32_FIND_DATA search_data;
       temp = refvecFiles+ "\\\\";
       refvecFiles += "\\\\*.*";        


       HANDLE handle = FindFirstFile(refvecFiles.c_str(), &search_data);

       if (INVALID_HANDLE_VALUE == handle) 
        {
            return 0;
        }

        do{
                    if((search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))      //Directory
                        {    string filePath =search_data.cFileName;
                            if (strcmp(".", filePath.c_str()) && strcmp("..", filePath.c_str()))             
                                {
                                    if (filePath == "$RECYCLE.BIN" || filePath == "$Recycle.Bin")
                                    continue;
                                    temp1=search_data.cFileName;
                                    temp2=search_data.dwFileAttributes;
                                    myList.push_back(temp+temp1);
                                    telDIR++;
                            }
                        }else{
                                siZe=(search_data.nFileSizeHigh * (MAXDWORD+1)) + search_data.nFileSizeLow;
                                siZekB=((search_data.nFileSizeHigh * (MAXDWORD+1)) + search_data.nFileSizeLow)/1024;
                                temp1=search_data.cFileName;
                                temp2=search_data.dwFileAttributes;
                                if ((search_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0)
                                {   TotalUsed=TotalUsed+siZekB;
                                    if (siZekB>LargestFile){
                                        LargestFile=siZekB;
                                        LargestFileName=temp.substr(0, temp.size()) + "\\" + temp1;
                                    }
                                    telFILES++;
                                }else{
                                    TotalUsedHidden=TotalUsedHidden+siZekB;
                                    if (siZekB>LargestFileHidden){
                                        LargestFileHidden=siZekB;
                                        LargestFileNameHidden=temp.substr(0, temp.size()) + "\\" + temp1;
                                    }
                                    telFILESHidden++;
                                }
                        }

        }while      (FindNextFile(handle, &search_data) != 0);
       FindClose(handle);
       return 0;
    }
HB1963
  • 107
  • 1
  • 2
  • 11