Hi,
ich brauche Euch wieder einmal.
Ich habe folgenden Quelltext zum Üben in Visual Studio geschrieben.
Später wird ein ähnlicher Code in einem Atmel ATMega32 Platz finden.
Folgendes soll geschenen, was laut meines Wissens über C aber nicht
funktionieren sollte:
In das leere globale Char Array gStr[] soll mit strncpy ein mittels
einer Funktion übergebenen Zeigers das Array hineinkopiert werden und
später ausgegeben werden. Nun frgae ich mich: Ein globales Array wird ja
mit einer festen Größe erzeugt. Wenn man jetzt das Array mittels strncpy
quasi vergrößert werden da nicht der Stack oder der Datenbereich
teilweise überschrieben? Warum also wird das int i = 123 nicht
überschrieben bzw. warum gibt der Compiler keine Warnungen oder
Fehlermeldungen aus? Ich erzeuge ja nichts mit malloc aufm Heap?
Habe ich da einen Denkfehler?
Compileroptimierungen?
Hilft mir bitte mal ;)
Bernhard N. schrieb:
> später ausgegeben werden. Nun frgae ich mich: Ein globales Array wird ja> mit einer festen Größe erzeugt. Wenn man jetzt das Array mittels strncpy> quasi vergrößert
Da wird nichts vergrößert.
Wenn du das Array mit sagen wir mal 10 Zeichen definierst und strncpy
den Auftrag gibst, dort 20 Zeichen abzulegen, dann wird strncpy zwar in
das Array schreiben (die ersten 10 Zeichen) aber auch Speicher
beschreiben, der nicht zum Array gehört.
Es ist einzig und alleine dein Bier dafür zu sorgen, dass so etwas nicht
passiert. Keine str... Funktion nimmt dir diese Verantwortung ab.
Bernhard N. schrieb:
> teilweise überschrieben? Warum also wird das int i = 123 nicht> überschrieben bzw.
Weil es von den Details abhängt, wie der Compiler die Dinge im Speicher
anordnet.
Probier mal
int j = 567;
char gStr[] = "";
int i = 123;
also eine Variable davor und eine danach. Meistens ist es so, dass eine
der beiden danach Schrott enthält weil der Compiler die Variablen ja
auch nicht irgendwie willkürlich im Speicher anordnet, sondern eine
bestimmte Reihenfolge einhält.
Genau das bedeutet: undefined behaviour
Alles mögliche kann passieren. Inklusive "sieht so aus als ob es geht".
Aber ein Fehler, den man nicht sieht ist immer noch ein Fehler.
> warum gibt der Compiler keine Warnungen oder> Fehlermeldungen aus?
Da müsste er ständig warnen. Der Compiler weiß ja nicht, wie groß der
String ist, den du ins Array kopieren willst.
(OK. Mit einer aufwändigen Analyse könnte er das IN DEINEM FALL
rausfinden. Aber im Allgemeinen geht das nicht. Array und Funktion die
das Array beschreibt müssen ja nicht in derselben Compilation Unit sein)
Du kannst einen globalen Pointer nehmen und mit strndup() statt
strncpy() kopieren. Allerdings ist dann das freigeben des Speichers in
Deiner Verantwortung (wird oft vergessen).
Rene H. schrieb:
> Doch strdup allociert Speicher.
OK.
Mit Ausnahme von strdup kümmert sich keine einzige str... Funktion
darum, ob zu beschriebende Speicherbereiche gross genug sind.
Aus dem ganz simplen Grund, weil man in C aus einem Pointer nicht
ablesen kann, wie gross der Speicher ist auf den er zeigt. Und die
strn... Funktionen kann man ja auch anlügen ohne dass sie es merken.
Der Compiler macht Dich auf "Speicher-Sauereien" nicht aufmerksam. Das
liegt in der Hand des Programmierers im und mit dem Speicher zu denken.
Hast Du da etwas falsch gemacht, stürzt Deine Software nicht
deterministisch ab.
Wow, was für eine Antwort Flut. Danke erstmal an Alle, auch den Tipp mit
strdup, kannte ich noch nicht. Speicher freimachen mache ich dann
natürlich.
Ich spiele mal weiter mit dem Beispielcode herum.
Gruß
Bernhard N.
Bernhard N. schrieb:
> Wow, was für eine Antwort Flut. Danke erstmal an Alle, auch den Tipp mit> strdup, kannte ich noch nicht. Speicher freimachen mache ich dann> natürlich.
Das sagst du jetzt so :-)
Karl heinz Buchegger schrieb:
> Bernhard N. schrieb:>> Wow, was für eine Antwort Flut. Danke erstmal an Alle, auch den Tipp mit>> strdup, kannte ich noch nicht. Speicher freimachen mache ich dann>> natürlich.>> Das sagst du jetzt so :-)
Gib mir ein free() und ich bau das dann ein. Dann vergesse ich es nicht
^^
Bernhard N. schrieb:
> Karl heinz Buchegger schrieb:>> Bernhard N. schrieb:>>> Wow, was für eine Antwort Flut. Danke erstmal an Alle, auch den Tipp mit>>> strdup, kannte ich noch nicht. Speicher freimachen mache ich dann>>> natürlich.>>>> Das sagst du jetzt so :-)>> Gib mir ein free() und ich bau das dann ein. Dann vergesse ich es nicht> ^^
:-) Wenns nur in der Praxis so einfach wäre :-)
(vereinfachter Code, der so simpel in einem realen Programm nicht
auftaucht. Wenn sowas passiert, dann immer in der verschärften Version,
verteilt auf 8 Funktionen in 6 Files über 12 Bildschirmseiten :-)
hehe, ja wirkt etwas gekünstelt.
Aber raub mir doch nicht einfach die Illusion, dass das Programmieren
hier so viel Frust erzeugen kann. Ich will mir mein naives Weltbild
nicht so einfach zerstören. ^^
Gruß
Bernhard