malloc in einer Funktion



  • Hallo!

    Variablen verlieren beim Verlassen der Funktion ihre Gültigkeit. Trifft das auch auf malloc zu? Beispiel:

    int main ()
    {
      FILE * fp;
      char * string_p;
    
      get_string (fp, string_p);
    
      printf ("%s", string_p);
    
      return (0);
    }
    
    void get_string (FILE *fp, char *string_p)
    {
       size_t len = 0;
       i = 0;
    
       /* stellt die Länge des Strings fest */
       while (getc(fp) != EOF)
       {
         ++len;
       }
    
       /* reserviert Speicher dafür */
       string_p = (char *)malloc((len+1) * sizeof(char));
    
       while ((c = getc(fp)) != EOF)
       {
         string_p[i] =  c;
         ++i;
       }
       string[++i] = '\0';
    }
    

    Wird die Funktion printf mir den korrekten String ausgeben?

    Gruß
    Michael



  • Ich habe deinen Code nicht gelesen, aber der Speicher steht dir auch nach dem verlassen der Funktion solange zr Verfügung bis du ihn mit free freigibst.



  • Vorsicht! Der Speicher bleibt zwar verfügbar, aber Du hast keinen Zugriff mehr darauf (C kennt 'call by reference' nicht). Sicherheitshalber ist der Code aber unsinnig (und sollte auch nicht compilieren -- /bitte/ Quelltext hier mit Copy&Paste einfügen. Danke.)



  • So würds gehen, was du vorhast:

    int main () 
    { 
      FILE * fp; 
      char * string_p; 
    
      string_p=get_string (fp, string_p); 
    
      printf ("%s", string_p); 
    
      free(string_p);
    
      return (0); 
    } 
    
    char *get_string (FILE *fp, char *string_p) 
    { 
       size_t len = 0; 
       i = 0; 
    
       /* stellt die Länge des Strings fest */ 
       while (getc(fp) != EOF) 
       { 
         ++len; 
       } 
    
       /* reserviert Speicher dafür */ 
       string_p = (char *)malloc((len+1) * sizeof(char)); 
    
       while ((c = getc(fp)) != EOF) 
       { 
         string_p[i] =  c; 
         ++i; 
       } 
       string_p[++i] = '\0'; 
    
       return(string_p);
    }
    

    oder auch so müsste es funktionieren:

    int main () 
    { 
      FILE * fp; 
      char * string_p; 
    
      get_string (fp, &string_p); 
    
      printf ("%s", string_p); 
    
      free(string_p);
    
      return (0); 
    } 
    
    void get_string (FILE *fp, char **string_p) 
    { 
       size_t len = 0; 
       i = 0; 
    
       /* stellt die Länge des Strings fest */ 
       while (getc(fp) != EOF) 
       { 
         ++len; 
       } 
    
       /* reserviert Speicher dafür */ 
       *string_p = (char *)malloc((len+1) * sizeof(char)); 
    
       while ((c = getc(fp)) != EOF) 
       { 
         *string_p[i] =  c; 
         ++i; 
       } 
       *string_p[++i] = '\0'; 
    }
    

    Kann es sein, dass du noch vergessen hast ein paar Befehle mit reinzuschreiben?? Wo ist die Dateiverarbeitung?



  • Hallo!

    Besten dank Euch allen! Habe es hinbekommen.

    Gruß
    Michael



  • Von der Anwendung her einfacher wäre es, einfach einen Buffer mitzugeben - dann musst du den Speicher nachher nicht von Hand freigeben. ALso etwa so:

    char *get_string (FILE *fp, char *string_p)  
    {  
       size_t len = 0;  
    
       for(char c; (c = fgetc(fp)) != EOF; ++len)  
         string_p[len] = c;
       string_p[len] = '\0';  
    
       return string_p; 
    }
    
    int main ()  
    {  
      FILE * fp = fopen("text.txt");  
      char buffer[1024];  //nur um ne Zahl zu nennen. 
    
      printf ("%s", get_string (fp, buffer));  
    
      return 0;  
    }
    

    Sicherer wäre noch, die Länge des Buffers ebenfalls mitzugeben, um segfaults zu vermeiden:

    char *get_string(FILE *fp, char *string_p, int buflen)
    {
      size_t i = 0;
      for(char c; i < buflen - 1 && (c = fgetc(fp)) != EOF; ++i) 
        string_p[i] = c;
      string_p[i] = 0;
    
      return string_p;
    }
    
    int main ()  
    {  
      FILE * fp = fopen("text.txt");  
      char buffer[1024];  //nur um ne Zahl zu nennen. 
    
      printf ("%s", get_string(fp, buffer, 1024));  
    
      return 0;  
    }
    

    wobei du dann in diesem speziellen Fall auch gleich fread benutzen könntest:

    int main() 
    {
      FILE *fp = fopen("text.txt");
      char buffer[1024];
    
      fread(buffer, sizeof(char), 1024, fp)
      printf("%s", buffer);
    
      return 0;
    }
    


  • AJ schrieb:

    So würds gehen, was du vorhast:

    int main () 
    { 
      FILE * fp; 
      char * string_p; 
     
      string_p=get_string (fp, string_p); 
     
      printf ("%s", string_p); 
    
      free(string_p);
     
      return (0); 
    } 
     
    char *get_string (FILE *fp, char *string_p) 
    { 
       size_t len = 0; 
       i = 0; 
        
       /* stellt die Länge des Strings fest */ 
       while (getc(fp) != EOF) 
       { 
         ++len; 
       } 
     
       /* reserviert Speicher dafür */ 
       string_p = (char *)malloc((len+1) * sizeof(char));
    

    Eben nicht.



  • @Daniel
    So und warum nicht? Kannst du mir dann erklären wie das realloc macht??



  • AJ schrieb:

    So und warum nicht?

    ich versuchs mal mit einem Beispiel:

    void f(char *p) { p = malloc(...); }
    int main() {
    /* 1 */
        char *p;
        f(p);
       /* bewirkt deiner Meinung nach, daß p auf etwas sinnvolles zeigt?
          Dem ist nicht so.
       */
    /* 2 */
       char c;
       f(&c);
       /* hier wird selbstverständlich die Speicherstelle von c nicht verändert! */
    }
    

    Kannst du mir dann erklären wie das realloc macht?

    Es gibt einen Zeiger auf den neu bereitgestellten Speicher zurück, falls welcher erreichbar war. Dabei verliert der alte Speicher, auf den das erste Argument verweist seine Gültigkeit (_das worauf es zeigt_). Andere interessante Details zu dieser Funktion stehen in der Doku.



  • @Daniel
    Wenn du dir meinen Code genau und GANZ angeschaut hättest, dann wäre dir aufgefallen, dass ich den Zeiger zurückgebe. So wie es eben realloc macht.

    Ich habe die behauptet, dass der Code, den du gepostest hast bei deinem letzten Eintrag, funktionieren würde. Ich behaupte sogar das Gegenteil so wie du.



  • Wenn Du jetzt noch eine sinnvolle Methode zur Längenbestimmung (und ein paar andere kleine Nachbesserung) anbietest, dann können wir den Thread sterben lassen. Leise, bitte.
    😉


Anmelden zum Antworten