[gelöst]char-Pointer + malloc() -> Länge wird ignoriert
-
Hi,
ich spiele hier gerade etwas mit char-Pointern und der Funktion malloc() rum.
Ich dachte eigentlich ich hätte die Problematik soweit verstanden, aber wie es Aussieht habe ich da doch noch Probleme beim Verständnis.Ich habe hier einen char-Array mit einer festen Länge von 255, in diesem char-Array steht ein Text. Hinzu kommt noch ein Pointer auf einen char um nun den Satz aus dem char-Array mit fester Größe in den char-Pointer zu "schreiben" habe ich mit malloc Speicher für die Länge des Arrays reserviert.
char str_Hallo[255]="Hallo Welt!"; char *str_Dyn; str_Dyn = (char*) malloc( sizeof(char) * strlen(str_Hallo) ); strcpy(str_Dyn, str_Hallo);
Das funktioniert soweit alles ganz gut und das Ergebnis dass am Schluss raus kommt, nämlich das in str_Dyn das selbe wie in str_Hallo steht habe ich auch so erwartet.
wenn ich jetzt aber im nächsten Schritt mit realloc mehr Speicher reserviere:
str_Dyn = (char*) realloc(str_Dyn, (sizeof(char) * (strlen(str_Dyn) + 4)));
und dann diesen Satz anhänge:
strcat(str_Dyn, "Das ist ein Test und sollte nicht gehen...");
wird der komplette satz an den char-Pointer angehängt.
Nach meine Verständnis dürfte in der Variable str_Dyn eigentlich nur Platz für "Hallo Welt!" + 4 Weitere Zeichen sein.
Ich Debugge das Programm mit GDB und erstelle mit Hilfe von gcc ein Debug-Release (Option -g). Könnte es auch daran liegen, dass das Array dann etwas größer ist.
Habe ich den Vorgang falsch verstanden oder läuft da was falsch.
Vielen Dank für eure Hilfe.
lg,
Fabi++
-
sizeof(char) ist per Definition = 1,
ein typecast bei malloc ist nur im C++ Umfeld nötig,
du musst auch ausreichend Platz für das abschließende '\0' reservieren, sodass es dann so aussieht:str_Dyn = malloc( strlen(str_Hallo)+1 );
Das realloc reserviert 4 Byte zusätzlich und ein strcat über diesen Bereich hinaus bedeutet undefiniertes Verhalten, d.h. es kann gut gehen oder nicht und das nicht bei jedem Programmlauf gleich.
-
@Wutz: Ersteinmal vielen Dank für deine Hilfe.
ein typecast bei malloc ist nur im C++ Umfeld nötig
Bist du die da sicher? Ich habe das an einigen Stellen auch schon anders gelesen.
du musst auch ausreichend Platz für das abschließende '\0' reservieren,
Klar, dass hatte ich nicht bedacht, bzw. vergessen.
Das realloc reserviert 4 Byte zusätzlich
Das bedeutet aber dann schon, dass ich 4 weitere Zeichen anhängen kann?
Oder ist das dann mehr?und ein strcat über diesen Bereich hinaus bedeutet undefiniertes Verhalten, d.h. es kann gut gehen oder nicht und das nicht bei jedem Programmlauf gleich.
Meine Überlegung war daher ja aber richtig?!
Der String "Hallo Welt!" + "Das" wäre dann aber vollkommen in Ordnung und zulässig, ohne das das Programm Probleme bekommen würde?
lg,
Fabi++
-
Fabi++ schrieb:
ein typecast bei malloc ist nur im C++ Umfeld nötig
Bist du die da sicher? Ich habe das an einigen Stellen auch schon anders gelesen.
Ja.
Fabi++ schrieb:
Das realloc reserviert 4 Byte zusätzlich
Das bedeutet aber dann schon, dass ich 4 weitere Zeichen anhängen kann?
Oder ist das dann mehr?Ja.
Max. 4, nicht mehr.Fabi++ schrieb:
und ein strcat über diesen Bereich hinaus bedeutet undefiniertes Verhalten, d.h. es kann gut gehen oder nicht und das nicht bei jedem Programmlauf gleich.
Meine Überlegung war daher ja aber richtig?!
Ja.
Fabi++ schrieb:
Der String "Hallo Welt!" + "Das" wäre dann aber vollkommen in Ordnung und zulässig, ohne das das Programm Probleme bekommen würde?
Ja.
-
Du schreibst damit halt stumpf in Speicher weiter, der dir nicht gehört, was undefiniertes Verhalten erzeugt. Undefiniertes Verhalten bedeutet, dass im C-Standard schlicht nicht steht, was eine Implementation in einem solchen Zusammenhang tun soll - so was kann zu einem Segfault führen, andere Daten, die in der Nähe gelagert sind, überschreiben, still funktionieren, später durch andere Zugriffe auf den Heap an eben dieser Stelle verändert werden oder eine Atombombe in der Nähe von Dallas zünden.
Zugegeben, letzteres ist eher unwahrscheinlich, aber eine Implementation, die es täte, verstieße nicht gegen den C-Standard. Was in deinem Fall wahrscheinlich passiert, ist, dass malloc den Speicher irgendwo hinter anderen Heap-Daten aber in einigem Abstand zum Ende der Speicherpage anlegt, so dass du dich immer noch in Speicher bewegst, den das Betriebssystem deinem Programm zugeordnet hat. Natürlich können im weiteren Programmablauf oben genannte Symptome weiterhin auftreten, und es garantiert dir auch niemand, dass du nicht doch mal am Ende der Page landest, also ist das so höchst unzuverlässig.
-
Super, vielen Dank für deine Hilfe.
Jetzt ist das Thema klar.
@seldon:
oder eine Atombombe in der Nähe von Dallas zünden
LOL...das ist mal eine nette Erklärung. Das bleibt im Gedächtnis haften.
Was in deinem Fall wahrscheinlich passiert, ist, dass malloc den Speicher irgendwo hinter anderen Heap-Daten aber in einigem Abstand zum Ende der Speicherpage anlegt, so dass du dich immer noch in Speicher bewegst, den das Betriebssystem deinem Programm zugeordnet hat.
Das klingt logisch. So hatte ich das auch gelesen bzw. gelernt, war mir aber wie im ersten Post gesagt nicht mehr ganz sicher ob ich das jetzt richtig verstanden habe.
und es garantiert dir auch niemand, dass du nicht doch mal am Ende der Page landest, also ist das so höchst unzuverlässig.
Ein wenig Arbeit sollte der Programmierer ja auch noch übernehmen ;).
Danke nochmal für die tolle und schnelle Hilfe.
lg,
Fabi++
-
Fabi++ schrieb:
@Wutz: Ersteinmal vielen Dank für deine Hilfe.
ein typecast bei malloc ist nur im C++ Umfeld nötig
Bist du die da sicher? Ich habe das an einigen Stellen auch schon anders gelesen.
Ich glaube Wutz kannst du da vertrauen. Du weißt das jetzt natürlich nicht, aber er ist einer der erfahrensten Teilnehmer im C Forum. Er hat jedenfalls vollkommen Recht. Ob man malloc casten soll oder nicht ist eine alte Streitfrage. Fakt ist, man brauchst es nicht zu casten und unnötige Sachen lässt man eben weg. Fakt ist auch, dass man das gleiche Programm dann nicht mehr mit einem C++-Compiler übersetzen kann. Das ist aber eine eher hypothetische Situation in der das mal nötig wäre. Der Konsens unter C Programmierern ist es aber eher, malloc nicht zu casten und dies als schlechten Stil anzusehen. Siehe Pro und Contra:
http://c-faq.com/malloc/cast.html
http://c-faq.com/malloc/mallocnocast.htmlDas realloc reserviert 4 Byte zusätzlich
Das bedeutet aber dann schon, dass ich 4 weitere Zeichen anhängen kann?
Oder ist das dann mehr?
[/quote]Nein, es sind 4. Wie sollte das mehr sein?und ein strcat über diesen Bereich hinaus bedeutet undefiniertes Verhalten, d.h. es kann gut gehen oder nicht und das nicht bei jedem Programmlauf gleich.
Meine Überlegung war daher ja aber richtig?!
Prinzipiell ja, insofern als dass dein Programm fehlerhaft war. Deine Überlegungen sind aber insofern falsch, als dass du nicht erwarten darfst, dass C dich vor Fehlern schützt. In C wird zuerst einmal immer angenommen, dass der Programmierer sich genauestens auskennt und ganz genau weiß, was er tut. Deshalb gibt es keinerlei Sicherheitsabfragen. Dies ermöglicht es einerseits extrem effizienten Code zu schreiben, ist aber natürlich wie du merkst nicht unbedingt anfängerfreundlich.
Der String "Hallo Welt!" + "Das" wäre dann aber vollkommen in Ordnung und zulässig, ohne das das Programm Probleme bekommen würde?
Ja, sofern du das Plus-Zeichen dort nur symbolisch meinst. In C kannst du Zeichenketten jedenfalls nicht mit '+' aneinanderhängen.
edit: Ich bin einfach viel zu langsam. Blöde deutsche Tastatur an der ich gerade sitze. Ich finde die ganzen Umlaute nicht
.
-
Nein, es sind 4. Wie sollte das mehr sein?
Ich meinte schon 4, oder verstehe ich deine Frage jetzt falsch?
Deine Überlegungen sind aber insofern falsch, als dass du nicht erwarten darfst, dass C dich vor Fehlern schützt. In C wird zuerst einmal immer angenommen, dass der Programmierer sich genauestens auskennt und ganz genau weiß, was er tut. Deshalb gibt es keinerlei Sicherheitsabfragen.
Das ist mir klar, deshalb wollte ich hier nochmal nachfragen um auf Nummer sicher zu gehen. Strings (bzw. char-Arrays) sind in C ja auch ein Thema für sich.
Dies ermöglicht es einerseits extrem effizienten Code zu schreiben, ist aber natürlich wie du merkst nicht unbedingt anfängerfreundlich.
Meiner Meinung überwiegen hier die Vorteile aber doch sehr.
Zumindest empfinde ich die Sprache viel angenehmer als z.B. Java oder VB.NET.
Aber das würde an dieser Stelle jetzt zu weit gehen.Ja, sofern du das Plus-Zeichen dort nur symbolisch meinst.
Jap...
In C kannst du Zeichenketten jedenfalls nicht mit '+' aneinanderhängen.
Ist bekannt.
Der Konsens unter C Programmierern ist es aber eher, malloc nicht zu casten und dies als schlechten Stil anzusehen.
Das ist mir jetzt komplett neu, kann aber auch sein, ich habe das mit dem cast aus einem C++ Buch. Bin mir da nicht mehr ganz sicher.
So, aber jetzt geh ich ins Bett.
Dann mal gute Nacht miteinander.lg,
Fabi++
-
Zumindest ich halte einen Cast von malloc ( und voidzeigern insgesamt) für störend im Lesefluss
char *tmp=malloc(15);
Da ist doch sofort klar dass ich 15 bytes speicher reserviere. Ob die jetzt für nen char* oder nen int* sind is doch bei malloc absolut egal.
void *ptr; char *c_ptr; ptr=c_ptr;
Hier ist sofort klar dass ptr auf dieselbe Stelle wie c_ptr zeigt, da ist der Typ auch absolut Wurst
void *ptr; int num=5; ptr=#/* kein cast, wie oben */ *(int*)ptr=2;
Hier muss natürlich ein cast sein, das is die einzige Situation wo man void* casten sollte