SIGSEGV-Fehler bei rekusivem Duchlauf



  • Hi,
    Ich baue gerade ne Funktion zum rekurisven Durchsuchen von Ordner. Die sieht momentan wie folgt aus:

    void SearchDataInFolder(HANDLE hwd,WIN32_FIND_DATA *DataStruct)
    {
        while(FindNextFile(hwd,DataStruct) == true)
        {
    
            if (DataStruct->cFileName[0] != '.')
            {
                //Wenn Ordner->Zähler hoch->In Ordner
                if (DataStruct->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    FolderCnt++; //globaler int
                    //hier ist der Fehler
                    SearchDataInFolder(hwd,DataStruct);
                }
                //Wenn Datei->Zähler hoch
                else DataCnt++; //globaler int
            }
        }
        FindClose(hwd);
    }
    

    Ein einmaliger Durchlauf(ohne checken der Unterordner) klappt ohne Probleme, wenn ich jedoch auch in die Unterordner gehen will macht mein Programm erstmal gar nichts und dann kommt ein Speicherfehler (der Debugmodus nennt das ganze SIGSEGV - hab bei Wikipedia geschaut, aber das half mir nicht viel...)
    ALso es ist ein Problem mit dem Spichermanagment, jedoch wies sich nicht genau wo,wie und warum....

    Zum erst-Aufruf der Funktion :

    ...
        HANDLE hwd;
        WIN32_FIND_DATA DataStruct;
    ...
        //StartPath ist ein ganz normaler String (mit *) wie z.B. "C:\\Test\\*"
        hwd = FindFirstFile(StartPath,&DataStruct);
        SearchDataInFolder(hwd,&DataStruct);
    ...
    

    P.S. Kann sein, dass der Thread besser ins C++-Forum passt, aber da die Funktion hauptsächlich aus WinApi-Befehlen besteht....



  • Du veränderst den Dateinamen der Ordnersuche nicht. Du musst bei dem gefundenen Ordnernamen wieder das sternchen und den Ursprungspfad anhängen, damit es Funktioniert. Außerdem musst du immer eine neue Suche starten:

    void SearchDataInFolder(HANDLE hwd, LPCWSTR lpFolder)
    {
        DWORD len = (DWORD)wcslen(lpFolder);
        // Ordnername + \* muss da sein
        if(lpFolder[len - 1] == L'\\')
            lpFolder[len++] = L'*', lpFolder[len] = 0;
    
        // Neue suche beginnen
        WIN32_FIND_DATA wfd;
        HANDLE hFind = FindFirstFile(lpFolder, &wfd);
        // . ordner wird nicht beachtet, .. rausfiltern
    
        while(FindNextFile(hwd, wfd))
        {
    
            if (wfd.cFileName[0] != '.')
            {
                //Wenn Ordner->Zähler hoch->In Ordner
                if (DataStruct->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    FolderCnt++; //globaler int
                    //Neuer Pfad für rekursive funktion
                    WCHAR Path[MAX_PATH];
                    // Sternchen entfernen
                    lpPath[len - 1] = L"\0";
                    PathCombine(Path, lpFolder, wfd.cFileName);
                    // Sternchen wieder hin
                    lpPath[len - 1] = L"*";
                    DWORD len2 = (DWORD)wcslen(Path);
                    // Sternchen an neuen Pfad hinzufügen
                    Path[len2] = L'\\';
                    Path[len2 + 1] = L'*';
                    Path[len2 + 2] = L'\0';
                    // Suchen
                    SearchDataInFolder(hwd,DataStruct);
                }
                //Wenn Datei->Zähler hoch
                else DataCnt++; //globaler int
            }
        }
        FindClose(hFind);
    }
    


  • Zusatz:
    Da der Ordnername nicht geändert ist rufst du die Funktion immer mit dem gleichem Namen auf ==> Stack overflow. Das wäre so als würdest du in einer unendlichen Schleife arbeiten nur, dass der Stack eben mit den returnadressen zugemüllt wird.



  • Achso... Ok, danke 🙂



  • Keine ursache, aber in dem code habe ich vergessen das handle hwn durch hFind zu ersetzen und das bei der Funktionssignatur rauszumachen.



  • Joa, hab ich gesehen, hab den aber auch nicht 1zu1 kopiert 😃
    Ich habs nun geschafft, dass alles funktioniert, nur geht der folgende Aufruf nicht immer:
    Ich hab einen Testordner mit folender Herachie angelegt:

    D:\t->a->c->Datei
            ->Datei    
            ->Datei
         ->b->Datei
    

    a,b,c sind Ordner. a enthält einen Unterordner und 2 Dateien. C(Unterordner von a) eine Datei und B ebenfalls eine Datei.
    Mein Programm findet aber nur 3 Dateien und 3 Unterordner- daher irgendwo wird was unterschlagen, ich denke mal die Datei die sich in Ordner b befindet...
    Aber warum?
    Hier der Code:

    void SearchDataInFolder(char *StartPath)
    {
        char TempStartPath[1024] = {'\0'};
        unsigned int i = 0;
    
        HANDLE hwd;
        WIN32_FIND_DATA DataStruct;
    
        //Das was auf in dem Pointer steht in die lokale Variable,um die später zu verändern
        while (StartPath[i] != '\0')
        {
            TempStartPath[i] = StartPath[i];
            i++;
        }
    
        hwd = FindFirstFile(TempStartPath,&DataStruct);
    
        while(FindNextFile(hwd,&DataStruct) == true)
        {
    
            if (DataStruct.cFileName[0] != '.')
            {
                //Wenn Ordner->Zähler hoch->In Ordner
                if (DataStruct.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    FolderCnt++;
                    //Ändert halt den Pfad entsprechend
                    ChangePath(TempStartPath,DataStruct.cFileName);
                    SearchDataInFolder(TempStartPath);
                }
                //Wenn Datei->Zähler hoch
                else DataCnt++;
            }
        }
        FindClose(hwd);
    }
    


  • Ich hab mal die Ordner angelegt und den Code durchlaufen lassen und bin darauf gekommen, dass der ordner b als a\b\* durchsucht wird. Du musst nachdem du den Unterordner durchsucht hast den alten ordner wiederherstellen oder den char array extra für den unterordner anlegen --> TempStartPath in die ordnerbedingung verlegen.



  • Wird das so aber nicht schon gehandhabt?
    Man hat doch immer Instanzen der Variablen, daher es gibt mehrere TempPathStrings, jweils eine für jede ausgeführte Funktion.
    Darum pack ich die ja auch extra um am Anfang der Funktion, damit ich nicht die Variable der alten Funktion ändere oder hab ich da nun was falsch verstanden?



  • Schon aber dein ChangePath verändert den Pfad und ruft die neue Funktion auf, aber du tust danach den veränderten pfad nicht zurücksetzen.

    void SearchDataInFolder(char *StartPath)
    {
        char TempStartPath[1024] = {'\0'};
        unsigned int i = 0;
    
        HANDLE hwd;
        WIN32_FIND_DATA DataStruct;
    
        //Das was auf in dem Pointer steht in die lokale Variable,um die später zu verändern
        while (StartPath[i] != '\0')
        {
            TempStartPath[i] = StartPath[i];
            i++;
        }
        // TempStartPath ist D:\t\*
    
        hwd = FindFirstFile(TempStartPath,&DataStruct);
    
        while(FindNextFile(hwd,&DataStruct) == true)
        {
    
            if (DataStruct.cFileName[0] != '.')
            {
                //Wenn Ordner->Zähler hoch->In Ordner
                if (DataStruct.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                    FolderCnt++;
                    //Ändert halt den Pfad entsprechend
                    ChangePath(TempStartPath,DataStruct.cFileName);
                    // Nun D:\t\a\*
                    SearchDataInFolder(TempStartPath);
                }
                //Wenn Datei->Zähler hoch
                else DataCnt++;
                // Immer noch D:\t\a\* sollte aber D:\t\* sein
                // Beim 2. mal wird der ordner b angehängt --> D:\t\a\b\*
            }
        }
        FindClose(hwd);
    }
    


  • Achso...
    Ok, geänder und funzt DANKE


Anmelden zum Antworten