verschachtelete Struktur an Funktion übergeben
-
columbus schrieb:
In Janjan's Code ist wird nachdem Platz für 5 Zeiger geschaffen wurde diese 5 Plätze noch einmal mit einem Zeiger initialisiert. Aber es wird gar kein Platz geschaffen für die inneren Schachteln.
Doch, für die 'inneren Schachteln' hat er auch Speicher reserviert. Das kannst du sogar in doppelter Ausführung lesen, nämlich einmal als Quellcode und als Kommentar darüber in Zeile 23.
columbus schrieb:
Ich habe jetzt folgendes gebaut:
...if((outer_schachtel->my_schachtel = realloc(outer_schachtel->my_schachtel, 1 * sizeof(schachtel_1*))) == NULL)
...
Ich nehme an, du willst das Zeigerarray für jede neue Zeile vergrößern? Dafür musst du aber auch die Anzahl erhöhen, bei dir ist sie konstant.
columbus schrieb:
Dann bin ich mir auch nicht ganz sicher was das casten angeht. Ich habe es hier mal rausgenommen, aber in meinem Lieblingswerk zu C: "Darnell/Margolis C a software Engineering Approach" und in vielen anderen Werken die man so im Netz findet, wird fleissig gecastet (z.B. in diesem C von A bis Z aus dem Galileo-Verlag)
Dazu kannst du dir das hier angucken,
http://www.c-plusplus.net/forum/viewtopic-var-t-is-206606.html
da findest du ach, wie man realloc benutzen sollte.Gruß,
B.B.
-
nwp2 schrieb:
BTW: Ja, in C castet man malloc nicht.
falsch... in c verwendet man kein malloc
-
malloc? was ist das schrieb:
nwp2 schrieb:
BTW: Ja, in C castet man malloc nicht.
falsch... in c verwendet man kein malloc
schreib doch nicht son stuss, sonst glaubt das noch jemand.
-
ich wollte damit eigentlich nur sagen, das man sich den einsatz von malloc(), calloc() und realloc() gut überlegen sollte. da diese functionen fehleranfällig und langsam sind. wollts ja selbst auch nicht glauben, mußte aber gestern mal einen kurzen blick in den dlmalloc source code werfen, der mal die implementation von gcc dargestellt hat
um mal zu zeigen was man nicht machen sollte
void fn(){ char *buffer = malloc(25); sprintf(buffer,"%d",0xFFFFFF); free(buffer); }
sondern viel besser schöner und schneller
void fn(){ char buffer[25]; sprintf(buffer,"%d",0xFFFFFF); free(buffer); }
lg lolo
-
noobLolo schrieb:
void fn(){ char buffer[25]; sprintf(buffer,"%d",0xFFFFFF); :warning: free(buffer); :warning: }
"free(buffer);" gehört da natürlich nicht hin.
-
Noch genauer könnte man sich das sprintf sparen weil es eh statisch ist.
Also char buffer[] = "16777215";
Noch genauer gesehen tut die ganze Funktion nichts und kann daher komplett weggelassen werden.
Auch wenn mir das niemand glaubt, buffer[zahl] ist immer ganz schlecht.
-
nwp2 schrieb:
Noch genauer könnte man sich das sprintf sparen weil es eh statisch ist.
Also char buffer[] = "16777215";
Noch genauer gesehen tut die ganze Funktion nichts und kann daher komplett weggelassen werden.
Auch wenn mir das niemand glaubt, buffer[zahl] ist immer ganz schlecht.Mitdenken ist nicht deine Stärke, oder?
-
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 üblichestruct 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 39columbus 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.