Strings / Malloc / Functions



  • Bitte nicht hauen, aber so klar sind mir Pointer und Strings nicht ... Anfaengerfrage ...

    Wenn ich folgendes mache ...

    int main(void)
    {
    	unsigned char *test_pnt = "123456789";
    	unsigned char *dummy = "abcdefghi";
    	test_pnt = test_func(dummy);
    
    	printf("Result: %s",test_pnt);
    }
    
    unsigned char *test_func (unsigned char *test_val)
    {
    	char *test_str;
    	int x;
    	test_str = (char *)malloc((10) *sizeof(char));
    
    	for (x=0; x<9; x++)
    	{
    		*(test_str + x) = *(test_val + x);
    	}
    	return test_str;
    }
    

    ... wird dann mit jedem Aufruf von test_func ein Speicherbereich belegt und nicht wieder freigegeben?? Oder wird, wie fuer z.B. die Variable "x", automatisch nach Beendigung der Funktion, der mit malloc reservierte Speicher wieder freigegeben?

    ... sollte die Funktion test_func doch eigentlich Muell "returnen", da test_str dann gar nicht mehr existiert ... tut test_func aber nicht.

    Gruss und Danke!!

    Juergen



  • Du musst den unterschied zwischen Pointern, und den Speicherbereich auf den sie zeigen, verstehen.

    Der reservierte Speicher bleibt erhalten, solange du ihn nicht mit free freigibst. Das gilt auch, wenn sich der Pointer nach verlassen der Funktion in wohlgefallen auflöst.
    Deswegen bleibt der Speicher erhalten auch nach verlassen der Funktion.
    Und mit jeden Aufruf wird ein neues Stück reserviert, bis nix mehr da ist.

    Du kannst auch beliebig viele Pointer haben, die auf die selbe Adresse zeigen.



  • Danke Sepp!

    Letztendlich suche ich nach einer eleganten Moeglichkeit Strings beliebiger Laenge aus Funktionen zurueckzugeben. Bisher tue ich dies ueber Var-Defs, die in allen Funtionen gueltig sind. Finde ich aber ziemlich haesslich und unuebersichtlich.
    Gibt's da nicht etwas besseres? Koenntest Du mich in die richtige Richtung schubsen? "Googlen" ergab immer nur globale Var-Definitionen.



  • Wieso?
    Deine Methode oben ist doch schon ok.

    In der Funktion reservierst du mit malloc den Speicher, füllst ihn und lieferst den Pointer auf den Speicher zurück.
    Die Länge des Strings brauchst du nicht extra zurückliefern, da die Strings ja mit 0 terminiert sind.
    Du musst aber natürlich dafür sorgen, dass der Speicher wieder freigegeben wird.
    Außerdem musst du natürlich noch testen, ob der Speicher reserviert werden konnte und dann ggf. NULL zurückliefern.
    Dann natürlich den Speicher nicht freigeben.

    int main(void)
    {
       char* test_pnt = NULL;
    
        test_pnt = test_func();
       if (!test_pnt) return -1;
    
       printf("Result: %s\n",test_pnt);
       free(test_pnt);
       return 0;
    }
    
    char *test_func ()
    {
        char *test_str;
        int x;
        test_str = malloc(10); //sizeof (char) ist immer 1 
        if (!test_str) return test_str; 
    
        for (x=0; x<9; x++)
        {
            test_str[x] = x+48;
        }
        test_str[9] = 0; //wegen 0 Terminierung
    
        return test_str;
    }
    


  • Hmm, richtig, ist ja gar nicht so schwer ... nur was ich nicht sooo schoen finde, ist dieses malloc innerhalb der Funktion und das zugehoerige free ausserhalb. Aber da fuehrt wohl kein Weg dran vorbei. Ist nicht unbedingt mein Verstaendnis von Strukturierung ... vielleicht bin ich auch einfach nur zu pingelig ;-))

    Danke nchmals!

    Juergen



  • Vielleicht solltest du über einen Umstieg nach C++ nachdenken.



  • Würde man in C nicht normalerweise einen Buffer samt Länge übergeben, so nach dem Motto

    char *test_func(char *dest, size_t dest_len, char const *src) {
      /* Kram in dest schreiben, aber nicht mehr als dest_len - 1 Zeichen plus \0 am Ende */
      return dest;
    }
    
    /* ... */
    
    char buf[100];
    puts(test_func(buf, 100, "Hello, World!")); /* zum Beispiel */
    


  • Desnaturado schrieb:

    Letztendlich suche ich nach einer eleganten Moeglichkeit Strings beliebiger Laenge aus Funktionen zurueckzugeben.

    Dann schau dir mal an, ob C++ was für dich ist. 😃

    Desnaturado schrieb:

    Hmm, richtig, ist ja gar nicht so schwer ... nur was ich nicht sooo schoen finde, ist dieses malloc innerhalb der Funktion und das zugehoerige free ausserhalb.

    Genau das ist das Hauptproblem bei der ganzen Geschichte. Zu schnell vergisst man einfach mal ein free und dann hast du ein Speicherleck. Und ein User der Funktion ist ohne richtige Doku gleich vollkommen aufgeschmissen. Deshalb ist in C der Vorschlag von 0xdeadbeef imo am besten. Du übergibst einfach von aussen einen Puffer mit Grössenangabe.


Anmelden zum Antworten