mikrocontroller.net

Forum: Compiler & IDEs strncpy und globaler String: Verständnisfragen


Autor: Bernhard N. (bernieserver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ;)
#include <stdio.h>
#include <string.h>

char gStr[] = "";
int i = 123;

void kopieren(unsigned char ZuVergleichen[],int size){
  strncpy(gStr,ZuVergleichen,size);
}

int main()
{
  unsigned char myString[] = "Burny";
  kopieren(myString,sizeof(myString));
  printf("%s\n",gStr);
  printf("%d\n",i);
  getchar();
  return 0;
}


Gruß

Bernhard

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rene H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Doch strdup allociert Speicher.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: Rene H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rene H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Bernhard N. (bernieserver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 :-)

Autor: Bernhard N. (bernieserver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 
^^

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 :-)

   char* tmp = "abcdef";

   if( i == 5 )
     tmp = strdup( somestring );

   ..... some operations

   // to free or not to free, that is the question
 }

Autor: Bernhard N. (bernieserver)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.