Dyn. Stringvektor wieder freigeben
-
Johann2 schrieb:
das "auf 0 setzen ist" muss ich so machen steht in meiner Aufgabe drin, aber ich weiß das das unsinnig is xD. Genauso auch den Typcast muss ich machen, verlangt der Prof.
das ist aber doof.
Johann2 schrieb:
Also liegt der Fehler wohl in der 9. Zeile?
Weil mit:PtrNamPtrArr = (char **)malloc(sizeof(char));
erstelle ich doch die dyn. Zeile von dem Vektor ...
ja, das ist falsch. es wird einfach nur speicher für ein byte geholt und dann ich einen char** gecastet. besser:
PtrNamPtrArr = malloc(sizeof(char**));
oder, wenn es deinem prof gefallen soll:
PtrNamPtrArr = (char**)(unsigned long)malloc(sizeof(char**)*sizeof(char));
-
oder, wenn es deinem prof gefallen soll:
Code:
PtrNamPtrArr = (char**)(unsigned long)malloc(sizeof(char**)*sizeof(char));magst du das etwas genauer erläutern, sind ziemlich kompliziert aus xD
Gruß
Johann
-
Du willst Speicher für ein char ** holen. Also muss es malloc(sizeof(char **)) heißen, nicht malloc(sizeof(char)). Der Rest ist eher sarkastisch gemeint gewesen. sizeof(char) ist 1, das kann man da reinmultiplizieren so oft man will und hat keinen Sinn. Der cast nach (unsigned long) tut auch nichts, weil er gleicht wieder nach (char **) zurückgecastet wird.
Genauso deine calloc-Version, die denselben Fehler hat. Du nimmst dir ein char und castest es um zum char **, das funktioniert nicht, weil char und char ** verschiedene Größen haben.
Vielleicht hilft das:
const int StringAnzahl = 5; char **strings = (char **)malloc(sizeof(char *)*StringAnzahl); //strings zeigt jetzt auf 5 stringpointer die nach nichts zeigen for (int i = 0; i<StringAnzahl; i++) strings[i] = (char *)malloc(sizeof(char)*10); //alle 5 strings in strings kriegen 10 Zeichen Speicher //jetzt ist alles initialisiert und man kann strings sinnvoll nutzen strings[0][0] = 'a'; //der 0te String hat als 0tes Zeichen ein a strings[3][7] = '\0'; //der dritte String hat als 7tes Zeichen ein Stringende Zeichen strings[5][1] = 'b'; //Fehler, string[5] gibt es garnicht!
-
Hmm, das wieder freigeben klappt aber immer noch nicht
Ich habe das jetzt mal ein bischen ausführlicher geschrieben:// dynStrVektor.cpp: mein Prog, nur stark komprimiert. #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXNAMLEN 51 /* Maximale Laenge inkl. \0 */ int main(void) { char ** PtrNamPtrArr = NULL, /* dyn. Stringvektor fuer Namen */ buf[MAXNAMLEN]; /* Einlesepuffer fuer einen Namen */ int iAktNam, /* Laufindex fuer jeden Namen */ len, /* Laenge eines Namens */ NamAnz = 4; /* fuer geforderte Namensanzahl */ /* Platz fuer NamAnz dyn. Strings reservieren */ PtrNamPtrArr = (char **)calloc(NamAnz, sizeof(char*)); for( iAktNam = 0; iAktNam < NamAnz; iAktNam++ ) { printf("Name %2d: ", iAktNam+1); fgets( buf, MAXNAMLEN, stdin); /* einen Namen einlesen */ len = strlen(buf)-1; /* Stringlaenge feststellen */ buf[len] = '\0'; /* letzes Zeichen loeschen */ fflush(stdin); /* ggf. Puffer leeren */ /* Speicher feur akt. Namen im Heap reservieren */ PtrNamPtrArr[iAktNam] = (char *)calloc(len, sizeof(char)); /* Namen aus dem Einlesepuffer in den Heap kopieren */ strcpy(PtrNamPtrArr[iAktNam], buf); } /* Speicher wieder freigeben klappt nicht */ for(iAktNam = 0; iAktNam < NamAnz; iAktNam++) free( PtrNamPtrArr[iAktNam] ); free(PtrNamPtrArr); printf("\n\n weiter mit [return]:"); setvbuf(stdin,NULL,_IONBF,0); setvbuf(stdin,NULL,_IOFBF,BUFSIZ); getchar(); return 0; }
Zu Zeile 23-25: Die Namen sollen ohne '\n' gespeichert werden
Gruß
Johann
-
Du hast immernoch sizeof(char) in Zeile 18, daher kannst du in PtrNamPtrArr nicht 4 Strings speichern wie du eigentlich willst, sondern nur einen.
-
deshalb sollte man
sizeof(datatype)
nicht verwenden, weil es zu Fehlern führt.PtrNamPtrArr = calloc(NamAnz, sizeof *PtrNamPtrArr));
da spielt überhaupt keine Rolle, was für ein Datentyp PtrNamPtrArr hat, das reserviert stets die benötigte Anzahl an Bytes. Siehe http://www.c-plusplus.net/forum/viewtopic.php?t=206606
btw.
fflush(stdin);
kann die CPU zum Schmelzen bringen.PS: wieso kompilierst du C Code mit einem C++ Compiler??? Entweder C schreiben, oder C++ aber nicht beides zusammen. Das führt zu Katastrophen.
-
PtrNamPtrArr = (char **)calloc(NamAnz, sizeof(char*));
ist doch logisch das gleiche wie:
PtrNamPtrArr = (char **)malloc(NamAnz*sizeof(char*));
und funzt auch nicht
@supertux
genauso wenig wie:PtrNamPtrArr = calloc(NamAnz, sizeof (*PtrNamPtrArr));
Ich hatte beide Vorschläge mit meiner Zeile 18. ersetzt doch die Fehlermeldung
während des ausführens ist gebliebenPS: wieso kompilierst du C Code mit einem C++ Compiler??? Entweder C schreiben, oder C++ aber nicht beides zusammen. Das führt zu Katastrophen.
Ist Vorschrift so, wahrscheinlich weil wir nächstes Semester auf c++ umsteigen werden ka
-
Johann2 schrieb:
...
len = strlen(buf)-1; /* Stringlaenge feststellen */
...^^ diese -1 sieht verdächtig danach nach fehler aus. mach mal lieber +1 daraus.
-
Bis eben stand da noch sizeof(char).
Ich habe keine Ahnung was du hast, ich habe den Code kompiliert und er läuft.
C und C++ mischen bzw. C mit einem C++-Compiler übersetzen und die wenigen Annehmlichkeiten von C++ genießen klappt super und endet nicht in einer Katastrophe.
-
nwp2 schrieb:
C und C++ mischen bzw. C mit einem C++-Compiler übersetzen und die wenigen Annehmlichkeiten von C++ genießen klappt super und endet nicht in einer Katastrophe.
die katastrophe haste spätestens dann, wenn du so'nen hingepfuschten C und C++ mischmach mit einem anderen compiler zum laufen kriegen willst.
-
nwp2 schrieb:
...ich habe den Code kompiliert und er läuft.
das zeigt doch nur, dass fehlerhafter code compilieren und manchmal sogar noch funktionieren kann. die 'strcpy's zerbröseln ihm den heap, jedes folgend 'malloc' oder 'free' könnte sich recht seltsam verhalten.
-
Ich habe keine Ahnung was du hast, ich habe den Code kompiliert und er läuft.
Bei mir tat er es aber nicht.
// dynStrVektor.cpp: mein Prog, nur stark komprimiert. #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXNAMLEN 51 /* Maximale Laenge inkl. \0 */ int main(void) { char ** PtrNamPtrArr = NULL, /* dyn. Stringvektor fuer Namen */ buf[MAXNAMLEN]; /* Einlesepuffer fuer einen Namen */ int iAktNam, /* Laufindex fuer jeden Namen */ len, /* Laenge eines Namens */ NamAnz = 4; /* fuer geforderte Namensanzahl */ /* Platz fuer NamAnz dyn. Strings reservieren */ PtrNamPtrArr = (char **)calloc(NamAnz, sizeof(char*)); for( iAktNam = 0; iAktNam < NamAnz; iAktNam++ ) { printf("Name %2d: ", iAktNam+1); fgets( buf, MAXNAMLEN, stdin); /* einen Namen einlesen */ len = strlen(buf); /* Stringlaenge feststellen */ buf[len-1] = '\0'; /* letzes Zeichen loeschen */ fflush(stdin); /* ggf. Puffer leeren */ printf("buf ist : %s und laenge ist: %d",buf,len); /* Speicher feur akt. Namen im Heap reservieren */ PtrNamPtrArr[iAktNam] = (char *)calloc(len, sizeof(char)); /* Namen aus dem Einlesepuffer in den Heap kopieren */ strcpy(PtrNamPtrArr[iAktNam], buf); } /* Speicher wieder freigeben klappt nicht */ for(iAktNam = 0; iAktNam < NamAnz; iAktNam++) free( PtrNamPtrArr[iAktNam] ); free(PtrNamPtrArr); printf("\n\n weiter mit [return]:"); setvbuf(stdin,NULL,_IONBF,0); setvbuf(stdin,NULL,_IOFBF,BUFSIZ); getchar(); return 0; }
Durch das
len = strlen(buf)-1;
was ich vorher in Zeile 25. stehen hatte wurde ja nur die Länge der sichtbaren Zeichen ermittelt. Anschließend mit
PtrNamPtrArr[iAktNam] = (char *)calloc(len, sizeof(char));
dementsprechend auch nur für einen String mit sichtbarer Zeichenanzahl reserviert. Dass '\0' hatte dann im Heap keinen Platz mehr gefunden.
Habe das -1 jetzt eine Zeile nach unten verfrachtet und es läuft jetzt.
Danke für dir HilfeGruß
Johann
-
Johann2 schrieb:
Habe das -1 jetzt eine Zeile nach unten verfrachtet und es läuft jetzt.
wird zufall sein. ich denke, ein -1 hat da nichts verloren, eher schon +irgendwas.
-
Klar, das
buf[len-1] = '\0';
löscht das '\n' das brauch ich nicht mit abspeichern