verschachtelete Struktur an Funktion übergeben



  • nwp2 schrieb:

    Auch wenn mir das niemand glaubt, buffer[zahl] ist immer ganz schlecht.

    Wenn "zahl" eine Variable ist, so daß Du ein VLA bekommst, riskierst Du einen potentiellen Stack-Überlauf. Ist "zahl" jedoch eine Konstante, gibt es nichts, was daran schlecht wäre.



  • Mit Zahl meine ich eine Konstante.
    Das Problem daran ist, dass man die Zahl nicht korrekt festlegen kann.
    Dieses übliche

    struct person{
        char name[80];
        int alter;
    };
    

    ist einfach falsch. Der Name von Personen ist nicht immer 79 Zeichen lang, somit ist char name[80] Blödsinn.

    Auch der Verweis dass malloc viel CPU frisst ist Quatsch, ich habe es noch nie erlebt, dass ein Programm hängt weil es nicht genug CPU-Power hat. Programme hängen nur ständig weil die Festplatte nicht nachkommt, CPU ist im Überfluss vorhanden seit es GHz-Rechner gibt (ja, ich weiß, Mikrocontroller).

    Ich weiß, diese Diskussion hatten wir schon. Ihr findet char buffer[12345] ganz toll und ich nicht. Niemand wird von seiner Position abweichen, deswegen braucht man darüber auch nicht zu reden.



  • nwp2 schrieb:

    Auch der Verweis dass malloc viel CPU frisst ist Quatsch

    Es ist kein Quatsch, sondern eine Tatsache. Bei malloc() muss beim Kernel mühsam nach Speicher gefragt werden, der Kernel muss sich dann erst darum kümmern. Arrays jedoch liegen auf dem Stack, dort muss einfach nur der Stackpointer verschoben werden -> SEHR viel schneller.



  • Janjan schrieb:

    SEHR viel schneller.

    Dauert statt einer Millisekunde 10. Das ist 1000% schneller. Trotzdem merkts keiner.
    Wenn man hingegen den buffer[12345]-Stil benutzt ist man immer großzügig mit dem Speicher und kommt ins Swappen, und das ist langsam.
    Mal ganz von Abstürzen und blödsinnigen Grenzen der Software abgesehen, weil die Buffergröße doch zu klein gewählt wurde.

    Edit: Der Punkt ist, dass man hier Korrektheit des Programms gegen ein paar CPU-Zyklen tauscht. Meiner Meinung nach ein ganz schlechter Tausch.



  • nwp2 schrieb:

    Der Punkt ist, dass man hier Korrektheit des Programms gegen ein paar CPU-Zyklen tauscht. Meiner Meinung nach ein ganz schlechter Tausch.

    Nein, der Punkt ist, dass man Dinge einfach halten will. Für jedes malloc() muss man auch einmal free() aufrufen. Das spart man sich mit Arrays.



  • Janjan schrieb:

    nwp2 schrieb:

    Der Punkt ist, dass man hier Korrektheit des Programms gegen ein paar CPU-Zyklen tauscht. Meiner Meinung nach ein ganz schlechter Tausch.

    Nein, der Punkt ist, dass man Dinge einfach halten will. Für jedes malloc() muss man auch einmal free() aufrufen. Das spart man sich mit Arrays.

    Zur Not nehmen wir alloca(), das braucht kein free().
    Leute die am heftigsten für malloc() plädieren, sind sowieso diejenigen, die free() sehr oft vergessen.



  • Stacksmasher schrieb:

    Zur Not nehmen wir alloca()

    Unportabel, unportabel!



  • nwp2 schrieb:

    Auch wenn mir das niemand glaubt, buffer[zahl] ist immer ganz schlecht.

    Geht das jetzt schon wieder los?
    🙂



  • Ich mag deine Signatur 😉



  • nwp2 schrieb:

    Auch wenn mir das niemand glaubt, buffer[zahl] ist immer ganz schlecht.

    Das ist doch Quatsch.
    Aber das hatten wir ja schon, das weißt du auch.



  • Also erst mal Danke für die Antworten! Auch wenn es teilweise etwas vom Thema abweichte 😉

    Also erst mal bin ich voll auf diese Erklärung: http://www.c-plusplus.net/forum/viewtopic-var-t-is-206606.html abgefahren. Die Zeiten dass ich mallocs/callocs gecastet habe sind vorbei.

    So jetzt habe ich aber ein Problem mit dem freigeben. Ich übergebe einer Funktion einen Zeiger auf einen Zeiger. In der Funktion wird an diesen Zeiger ein Zeiger auf eine Struktur gehängt. So würde ich gerne den Inhalt der Struktur in der Hauptroutine auswerten und erst dort den Speicher freigeben. Es lässt sich kompilieren, bricht dann aber und Valgrind meckert aber etwas von "Access not within mapped region". Wie macht man das denn sonst?

    typedef struct _knoten {
      char* vorname;
      char* nachname;
    }knoten;
    
    int namen_eintragen(knoten** mynode);
    
    main()
    {
      int rueckgabe = 0,
          zaehler   = 0;
      pKnoten** mynode = NULL;
    
      rueckgabe = namen_eintragen(mynode);
    
      // ausgabe...
      //printf(...
    
      // Freigabe
      // zuerst Freigabe der namen
      free(mynode[0]->vorname);
      free(mynode[0]->nachname);
      // dann Freigabe des Knotens
      free(mynode[0]);
      // und eventuell noch den Zeigerspeicher verringern mit realloc ...
    
    }
    
    int namen_eintragen(knoten** mynode)
    {
      char vor_name[]  = "Fritz\0";
      char nach_name[] = "Semmel\0";
    
      char* pVorname      = NULL;
      char* pNachname     = NULL;
      knoten** pivot_node = NULL;
      knoten*  local_node = NULL;
    
      /*! genug Platz schaffen für Zeiger auf Zeiger  */
      pivot_node = realloc(mynode, 2 * sizeof(**mynode));
      if(pivot_node != NULL)
      {
        mynode = pivot_node;
      }
      else
      {
        printf("Problem mit realloc\n");
      }
    
      /*! reserviere Speicher für den Vornamen         */
      if((pVorname = calloc (strlen(vor_name), sizeof(*pVorname))) == NULL)
      {
        printf("Problem beim Belegen von Speicher fuer wortstring\n");
        exit(-1);
      }
      strncpy(pVorname, vor_name, strlen(vor_name));
    
      /*! reserviere Speicher für den Nachnamen         */
      if((pNachname = calloc (strlen(nach_name), sizeof(*pNachname))) == NULL)
      {
        printf("Problem beim Belegen von Speicher fuer wortstring\n");
        exit(-1);
      }
      strncpy(pNachname, nach_name, strlen(nach_name));
    
      /*! lege Speicher für ein "knoten"-Element an */
      if((local_node = calloc (1, sizeof(*local_node))) == NULL)
      {
        printf("Problem beim Belegen von Speicher fuer das hdom_tspan-Element\n");
        exit(-1);
      }
      local_node->vorname = pVorname;
      local_node->nachname = pNachname;
    
      mynode = local_node;
    
      return 2;
    }
    


  • sehr schön du hast es geschafft für ein struct mit 2 membern 4x malloc/realloc/calloc aufzurufen. ich bin stolz auf dich, und nwp2 sicher auch. 👍

    lg lolo



  • noobLolo schrieb:

    sehr schön du hast es geschafft für ein struct mit 2 membern 4x malloc/realloc/calloc aufzurufen. ich bin stolz auf dich, und nwp2 sicher auch. 👍

    lg lolo

    😃

    columbus schrieb:

    ...
    Wie macht man das denn sonst?
    ...

    So schonmal nicht :p
    Es gibt einiges, was du noch überdenken musst, z.B. schreibst du in Zeile 39

    columbus schrieb:

    /*! genug Platz schaffen für Zeiger auf Zeiger  */
    

    Das ist prinzipiell falsch ( auch wenn hier tatsächlich zufälligerweise genug Speicher für einen Zeiger auf einen Zeiger reserviert wird ), damit reservierst du Speicherplatz für 2 Strukturelemente.

    Den Prototypen würde ich in deinem Beispiel als

    int namen_eintragen(knoten* mynode);
    

    deklarieren und dementsprechend die Funktion schreiben.



  • Okay das Beispiel ist für den Zweck ziemlich "oversized". Aber in meinem Problem übergebe ich ja ein Array von Zeigern einer Funktion, das wollte ich etwas vereinfachen, ist mir aber nicht sonderlich gelungen (sprich: mein Beispiel entspricht nicht meinem eigentlichen Problem). Die 2 im realloc ist schlicht ein vertipper.
    Aber ich habe mir auch schon gedacht dass wenn ich einen Zeiger auf einen Zeiger erzeuge und als solchen einer Funktion übergebe, wird das einfach nur als Kopie und nicht als Referenz interpretiert.
    Aber wenn ich der Funktion nur einen einfachen Zeiger gebe, kann sie damit nicht ArrayElemente "andocken".
    Also versuche ich es mit einem dreifach-Zeiger und übergebe diesem einer Funktion, die einen zweifach-Zeiger erwartet.

    Gruss Christian



  • columbus schrieb:

    Also versuche ich es mit einem dreifach-Zeiger und übergebe diesem einer Funktion, die einen zweifach-Zeiger erwartet.

    Dreifach-Zeiger? Gratuliere, du hast dich als Three-Star-Programmer qualifiziert! 🙂



  • Ja genau, vielen Dank und Tschüss.



  • columbus schrieb:

    Die 2 im realloc ist schlicht ein vertipper.

    Die doppelte Dereferenzierung ist auch ein Vertipper?


Anmelden zum Antworten