www.mikrocontroller.net

Forum: PC-Programmierung C pointer frage


Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi,

ich refreshe/erweitere z.Z. meine grundlegenden C kenntnisse mit diesem 
ebook
http://openbook.galileocomputing.de/c_von_a_bis_z/...

im kapitel pointer bin ich auf ein problem gestoßen, und zwar geht es um 
folgendes:

das hier funktioniert nicht, weil der string nach beenden der funktion 
aufgelöst wird. die variable wird aber nicht gelöscht, oder? es wird 
lediglich der speicherbereich freigegeben und zur sicherheit kompiliert 
der kompiler das nicht mehr(jedenfalls meiner) (gcc)
/* Fehler: Funktion gibt die Adresse
 * einer lokalen Variablen zurück. */
char *test1(void){
   char buffer[10];
   strcpy(buffer, "testwert");
   return buffer;
}

das hier aber funktioniert/soll funktionieren. umgeht man damit nicht 
nur die warnung des kompilers? der string wird doch trotzdem 
gelöscht/freigegeben oder nicht?
andererseits wundert mich das sich buffer nicht selbst übergeben lässt. 
schließlich ist buffer doch auch nur ein pointer auf das erste element 
:/ oder nicht?
/* Möglichkeit3: Einen Zeiger als Argument übergeben */
char *test4(char *ptr){
   char buffer[10];
   ptr = buffer;
   strcpy(buffer, "testwert");
   return ptr;
}


ich hoffe ihr könnt licht ins dunkel bringen :/

gruß

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dein buffer ist eine lokale Variable, die der Kompiler auf dem Stack 
ablegt.
Dein Pointer zeigt also auf den Stack.
Nach verlassen der Funtkion, ist der Zustand des Stacks unter dem 
Stackpointer undefiniert.

Du kannst zwar den Speicher noch auslesen, aber da kann mittderweile 
etwas völlig anderes draufstehen.

Edit: und ja test4 ist kompletter schwachsinn.

Autor: Vlad Tepesch (vlad_tepesch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
/* Möglichkeit3: Einen Zeiger als Argument übergeben */
char *test4(char *ptr){
   strcpy(ptr , "testwert");
   return ptr;
}
so wär es richtiger, allerdings wäre der Rückgabewert überflüssig.
Außerdem kann in der Funktion nicht sichergestellt werden, dass der 
übergebene Puffer groß genug ist.

wirklich korrekt wäre das:
void*test4(char *ptr, unsigned int len){
   static const char[] testText = "testwert";
   if(len > strlen(testText)
   { 
     strcpy(ptr , testText );
   }
}
wirklich sinn macht es aber natürlich immer noch nicht, ein eFunktion zu 
schreiben, die einen konstanten Text in einen Puffer kopiert.

Autor: guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@vlad


thx. der erste post hatte eigentlich schon alles geklärt ;)

die zweite lösung ist logisch
du schreibst per pointer direkt in eine von main deklarierte variable, 
dass es da keine probleme geben sollte ist klar



gruß

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> du schreibst per pointer direkt in eine von main deklarierte variable,
> dass es da keine probleme geben sollte ist klar

Das einzige Unschöne ist, dass der Aufrufer evtl. vor dem Aufruf nicht 
weißt, wie groß der Puffer sein muss. Damit muss man in C aber leben.*

Autor: Horst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
char *test(void) {
   char *ptr;
   ptr = malloc(9);
   strcpy(ptr , "testwert");
   return ptr;
}

und der aufrufende ist dann dafür verantwortlich, den speicher wieder 
frei zu geben.
Oder man baut darauf, dass man heutzutage eh soviel RAM hat.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn schon malloc(), dann lieber so:
char *test(void)
{
    static char *ptr;

    if (!ptr)
        ptr = malloc(9);

    if (ptr)
        strcpy(ptr, "testwert");

    return ptr;
}

So entspricht das wohl am ehesten dem, was im ersten Post versucht 
wurde.

Wobei der Aufrufer dann auch damit klarkommen muss, dass die Funktion 
evtl. NULL zurückliefert.

Andreas

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

Bewertung
0 lesenswert
nicht lesenswert
Andreas Ferber schrieb:
> Wenn schon malloc(), dann lieber so:

keine so gute Idee.

a) Da kannst du dir auch gleich einen static Buffer anlegen. So
   umgehst du wenigstens das Problem Out of Memory zu laufen.
b) man muss aufpassen, das man bei mehreren Aufrufen von test immer
   die gleiche Adresse zurückbekommt. Das kann unter Umständen auch
   kräftig ins Auge gehen, vor allen Dingen wenn dieser Pointer dann
   über mehrere Zwischenstufen in eine Funktion hineinübergeben wird,
   die ihrerseits wieder test() aufruft.

Solche lokalen cahing-Sachen können gut funktionieren, können aber auch 
mächtig ins Auge gehen und zu schwer findbaren Aliasing-Problemen 
führen.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> keine so gute Idee.
[...]

Das ist mir schon klar, ich wollte nur das offenbar intendierte 
Verhalten des Codes im ersten Post möglichst getreu mittels malloc() 
abbilden.

Andreas

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.