Speicherbefreiung nach curl-Funktion



  • Hallo liebe Forum-User,

    ich habe immer noch nicht ganz kapiert, wie man Speicher ordentlich befreit. Ich rufe mit libcurl dateien aus dem www ab und muss diese dann weiterverarbeiten. Alle 10sek, also immer wenn die Datei abgerufen wird, wird der vom Programm genutzte Speicher größer (laut Task Manager). Also wird es wohl irgendwo am folgenden Code liegen. Ich räume aber curl schon ordentlich auf (mit curl_easy_cleanup(ctx); und curl_global_cleanup) - und beim Rest weiss ich leider nicht, wie er aufgeräumt wird.

    Es wäre super, wenn mir jemand helfen würde - vielen Dank!

    datenAbrufer();
    
    void datenAbruferMatch(void)
    {
    	curl_global_init (CURL_GLOBAL_ALL);
    	CURL* ctx = curl_easy_init();
    	curl_easy_setopt(ctx, CURLOPT_URL, "http://meineurl.de/test.txt");
    	curl_easy_setopt(ctx, CURLOPT_NOPROGRESS, true);
    	curl_easy_setopt(ctx, CURLOPT_WRITEFUNCTION, sortMatchData);
    	curl_easy_setopt(ctx, CURLOPT_WRITEDATA, sortMatchData);
    	const CURLcode rc = curl_easy_perform( ctx ) ;
    	curl_easy_cleanup(ctx);
    	curl_global_cleanup();
    }
    
    size_t sortMatchData(void *buffer, size_t size, size_t nmemb, void *userp)
    	{
    		string allesZusammen = (char * )buffer;
    		char *test[4000]; char *test2[20];
    		string super; string vergleich;	
    		string m1s; string m2s;
    
    		int i; int j;
    		int anzahl2 = 0;
    		for (i=0; i<2000; i++)
    		{
    			test[i] = "";
    		}
    		int anzahl = split ('\n', (char*)buffer, test);
    
    		for (i=0; i<200; i++)
    		{
    			if (NULL != test[i]) {
    				super = (char*)test[i];
    				anzahl2 = split('|', (char*)super.c_str(), test2);
    
    				// Etwas herauslesen
    				vergleich = "testzeile";
    				if ((char*)test2[0] == vergleich) { glTestVar = (char*)test2[1]; }
    			}
    		}
    
    		*test = 0;
    		*test2 = 0;
    		return 1;
    	}
    


  • Hm...

    char *test[4000]; char *test2[20];
    

    Wofür brauchst du denn ein Array mit Char-Zeigern...?
    ...emm ja...: Was macht die Funktion split() ?
    bzw. wie lautet der Prototyp ? 🙄



  • Hallo CodeFinder,

    danke für deine Mühe! Split soll den String nach Trennzeichen zerlegen. Die Funktion habe ich gefunden (ich glaube in diesem Forum). Sie funktioniert auch sehr gut... und das mit den Zeigern hing alles irgendwie damit zusammen, dass ich den Text aus dem Buffer herausholen und der Split-Funktion übergeben musste. Leider bin ich noch in der mieserablen Lage, mehr zu "raten" als zu coden... Ich arbeite aber dran! Nur: Bei so einigen Fragen helfen die meisten Bücher nicht weiter...

    int split( char Sep, char *Source, char *Dest[]) 
    { 
       int count = 0; // Anzahl der gefunden TeilStrings 
       char *buffer = (char*) calloc( lstrlen( Source) + 1, sizeof(char)); // buffer max. so lang wie Source 
    
       for( int i=0, length=0; i<strlen(Source)+1; i++, length++) 
       { 
          if( Source[i] == Sep || Source[i] == '\0') 
          { 
             i+=1; // damit das Seperator-Zeichen übersprungen wird 
             Dest[count] = (char*) calloc( length + 1, sizeof(char)); // speicher reservieren 
             strncpy( Dest[count], buffer, length); // buffer in Destination kopieren 
             count++; // Anzahl erhöhen 
             length=0;   // buffer länge wieder auf 0 setzen 
             memset( buffer, 0, lstrlen( Source) + 1); // buffer inhalt wieder auf null ("") sezten 
          } 
          buffer[length] = Source[i];   // Zeichen in buffer umkopieren umkopieren 
       } 
    
       return count; // Anzahl zurück geben (+1, da bei 0 angefangen wurde zu zählen) 
    }
    


  • mehr zu "raten" als zu coden

    LOL 😃 😃

    so...: Dann will ich mal versuchen, das Rätsel zu lösen 😉 ... 💡

    char *buffer = (char*) calloc( lstrlen( Source) + 1, sizeof(char)); // buffer max. so lang wie Source
    

    Hier reservierst du Speicher der nie freigegeben wird, damit ist das Problem jawohl klar 👍



  • Gut gemeinter Rat: Schmeiss es weg und stell auf std::string um oder lass dich ins C Forum (danach siehts nämlich aus) verschieben.



  • jop, da hatta FireFlow Rescht...und noch n guten Rat, wenn du dir schon die Funktionen zusammen suchst und nur kopierst, dann würd wenigstens versuchen, sie zu verstehen 😉


  • Mod

    wenn ich calloc sehe, weiß ich sofort, dass ich in C land bin :p diese ganze buffer-kopier-umkopieraktion ist doch ein bisschen umständlich. und fehlerhaft, da ist schon mal ein leck in split - es fehlt ein free(buffer) vor dem return.

    split zerlegt den input in einzelne C-strings, die du selbst wieder freigeben musst. also

    int x = split( sep, src, dest );
    // ... verarbeitung des ergebnisses
    for ( int i = 0; i < x; ++i )
        free( dest[i] );
    

    oder, weil wir hier in C++ land sind

    for_each( dest, dest + x, free );
    

    andererseits, eben weil wir hier in C++ land sind, machen wir das ganze lieber mit richtigen strings und vergessen den calloc-mist

    std::vector<std::string> split(char sep, const std::string& src)
    {
        std::vector<std::string> result;
        if ( src.empty() )
            return result;
        std::string::size_type pos = 0;
        for ( ;; )
        {
            std::string::size_type pos2 = src.find( sep, pos );
            if ( pos2 == std::string::npos )
                break;
            result.push_back( src.substr( pos, pos2 - pos - 1 );
            pos = pos2 + 1;
        }
        result.push_back( src.substr( pos ) );
        return result;
    }
    

    noch nicht wirklich effizient, abre zumindest keine probleme mit der speicherfreigabe.



  • Großartig, danke! Alles funktioniert!

    Ich komme von PHP und VB und war einfach froh, dass ich irgendwo eine String Split Funktion gefunden hatte. - Dass die nicht so optimal war, hätte ich nie gemerkt, danke!

    Wo finde ich denn eine Übersicht darüber, welche Variablen und Objekte man nach Benutzung wieder löschen muss und welche nicht? - Manche Objekte haben ein ->release(), manche haben gar keine Methoden. Delete scheint nur für mit "new" erstellte Objekte in Frage zu kommen und "free" ist eine veralteter C-Baustein?!

    Ich Anfänger baue ein Programm und sehe mir dann hinterher im Task-Manager an, ob der genutzte Speicher mehr wird. Ich kann mir aber gut vorstellen, dass ihr Profis so etwas schon beim Erstellen des Codes bemerkt. Nach welchen Regeln richtet ihr euch?

    Nochmal danke an alle für die schnelle Hilfe, war wirklich super!



  • Wenn Du fremde Klassen nutzt musst du halt in der Doku schauen ob du eine Methode der Klasse zum Freigeben von Speicher aufrufen musst. Wenn es da keine Methode gibt, dann wird das meist über den Destruktur der Klasse realisiert.

    Diese spezielle Methode die jede Klasse hat wird automatisch aufgerufen wenn ein Objekt z.B durch Verlassen eines Anweisungsblocks "{" und "}" gelöscht wird oder wenn du DELETE nach einem NEW auf dem Zeiger des Objekts anwendest. Wenn Du eigene Klassen schreibst solltest Du in Deiner Destruktor Methode dafür sorgen dass der Speicher den Deine Klasse benutzt hat wieder freigegeben wird.

    {
    meinObjekt MeineKlasse;
    meinObjekt.meineMethode();
    } <-- hier wird automatisch der Destruktor aufgerufen
    
    meinObjekt = new MeineKlasse();
    meinObjekt->meineMethode();
    
    delete meinObjekt; <-- hier wieder Aufruf des Destruktors
    

    Gruß Chris


Anmelden zum Antworten