std::map und Rekursion



  • Hallo!
    Ich versuche eine map rekursiv zu füllen, aber das klappt leider nicht.
    Die Signatur meiner Methode sieht folgendermaßen aus:

    void MyClass::fillMap(const char* dir, map<char*,myVal*>* _map);
    

    Ich plane jetzt damit rekursiv durch die directories zu klappern, und bestimmte Teile bestimmter Files einzulesen, welche in der Map abgelegt werden. Mein Code sieht so aus:

    void MyClass::fillMap(const char* dir, map<char*,myVal*>* _map)
    {
    	DIR* pDir;
    	dirent* dp;
    	string sCurDir = dir;
    	string sCurFile;
          myVal* values = new myVal();
    
    	if(sCurDir.rfind("/") == sCurDir.length()-1)
    	{
    		sCurDir = sCurDir.substr(0,sCurDir.length()-1);
    	}
    
    	string::size_type pos = sCurDir.rfind("/");
    	string sCurKey = sCurDir.substr(pos+1,sCurDir.length()-1);
    
    	printf("Entering: %s\n",sCurDir.c_str());
    
    	pDir = opendir(sCurDir.c_str());
    	while((dp = readdir(pDir)) != NULL)
    	{
    		if(dp->d_type == DT_DIR)
    		{
    			if(strcmp(dp->d_name,".") && strcmp(dp->d_name,".."))
    			{
    				sCurDir += "/";
    				sCurDir += dp->d_name;
    				fillMap(curDir.c_str(),_map);
                            sCurDir = dir;
    
    			}
    		}
    		else if(dp->d_type == DT_REG)
    		{
    			sCurFile = sCurDir;
    			sCurFile += "/";
    			sCurFile += dp->d_name; 
    			myVal = loadValue(sCurFile);
    			//printf("file: %s\n",sCurFile.c_str());
    		}
    	} 
    	(void)closedir(pDir); 
    
    	printf("INSERTING!\n");
    	_map->insert(make_pair((char*)sCurKey.c_str(),myVal));
    	printf("key: %s,size: %i\n",sCurKey.c_str(),_map->size());
    
          /*nur zum testen*/
    	map<char*,CSprite*>::iterator it;
    	for(it = _map->begin(); it != _map->end(); it++)
    	{
    		printf("%s\n",it->first);
    	}
    	return;
    }
    

    Eigentlich sollte jetzt jede Value mit dem Verzeichnis-Namen als Key in der Map abgelegt sein. Doch nur der letzte Verzeichnisname ist am Ende als Key enthalten, und dann noch 2Mal irgendwelcher Garbage. Insgesamt werden jedoch 16 Inserts gemacht (sind ja auch 16 directories). Was mache ich denn nur falsch?

    Wäre nett wenn mir jemand helfen könnte,
    Bye!



  • Habs nur mal überflogen, aber ein Hinweis: du speicherts in deiner std::map einen Zeiger auf ein char-Feld. Erstmal tust du einfach das const wegcasten, das ist kein feiner Stil, und zweitens solltest du die Güktigkeit der Variablen beachten.

    Dein sCurKey ist nur in der Funktion gültig. Nach dem Verlassen der Funktion wird der std::string zerstört, du merkst dir in der std::map also einen Zeiger auf ungültigen Speicher, ich vermute mal, dass daher dein Müll kommt.

    map<std::string,myVal*>
    

    Das wäre besser.
    Bei myVal habe ich jetz nicht geschaut, auch hier musst du drauf achten, dass du einen Zeiger speicherst und der Speicherbereich auch wirklich noch gültig ist.



  • Danke für deine rasche Antwort, Pellaeon! Ich habe jetzt alle keys in der map, so wie sie gebraucht werden. Allerdings bekomm ich jetzt Seg-Faults beim Zugriff auf die Pointer von myVal; Das sollten aber zwingend Pointer sein, Objekte kommen nicht in Frage. Wie kann ich denn sicher gehen, dass die Pointer auch nach dem Aufruf der Methode wirklich noch existieren.



  • _map->insert(make_pair((char*)sCurKey.c_str(),myVal));
    

    myVal ist doch der Name des Types und nicht die Variable oder?

    myVal* values = new myVal();
    

    also müsstest du ja values reinhauen, weil das der Zeiger ist.

    Ansonsten new benutzt du ja schon, das ist richtig so. Darfst dann natürlich nicht das delete vergessen an entsprechender Stelle.



  • Ja, da sollte auch values und nicht myVal stehen. Ich hab den Code ein bissal vereinfacht und lange Ausdrücke rausgenommen, da ist mir wohl ein kleiner Fehler passiert. Trotzdem bekomme ich diese vermaledeiten Seg-Faults. Ich werd jetzt einfach mal einen myVal** mit in die Signatur reinschreiben, das sollte dann (hoffentlich) funktionieren, ist aber meines Erachtens nach keine schöne Lösung;

    void MyClass::fillMap(const char* dir, map<char*,myVal*>* _map, myVal** vals)
    {
    
    static int count = 0;
    ...
    /*an geeigneter Stelle*/
    vals[count] = new myVal();
    ...
    }
    


  • Also nocheinmal danke für deine Antwort, ich hab es jetzt hinbekommen. Der Fehler lag anscheinend an ganz anderer Stelle. Hätte ich eigentlich nicht für möglich gehalten, aber da hat eine Klasse ints mit ganz komischen Werten initialisiert. Ich hätte halt gedacht das 0 Standard wäre ^^



  • myVal = loadValue(sCurFile);
    

    Das Teil liefert auch wirklich einen Zeiger zurück?


Anmelden zum Antworten