C pointer frage

Gast #1796825
hi,

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

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)
1
/* Fehler: Funktion gibt die Adresse
2
 * einer lokalen Variablen zurück. */
3
char *test1(void){
4
   char buffer[10];
5
   strcpy(buffer, "testwert");
6
   return buffer;
7
}

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?
1
/* Möglichkeit3: Einen Zeiger als Argument übergeben */
2
char *test4(char *ptr){
3
   char buffer[10];
4
   ptr = buffer;
5
   strcpy(buffer, "testwert");
6
   return ptr;
7
}


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

gruß
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.
1
/* Möglichkeit3: Einen Zeiger als Argument übergeben */
2
char *test4(char *ptr){
3
   strcpy(ptr , "testwert");
4
   return ptr;
5
}
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:
1
void*test4(char *ptr, unsigned int len){
2
   static const char[] testText = "testwert";
3
   if(len > strlen(testText)
4
   { 
5
     strcpy(ptr , testText );
6
   }
7
}
wirklich sinn macht es aber natürlich immer noch nicht, ein eFunktion zu 
schreiben, die einen konstanten Text in einen Puffer kopiert.
Gast
@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ß
Gast
> 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.*
Gast
1
char *test(void) {
2
   char *ptr;
3
   ptr = malloc(9);
4
   strcpy(ptr , "testwert");
5
   return ptr;
6
}

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.
Wenn schon malloc(), dann lieber so:
1
char *test(void)
2
{
3
    static char *ptr;
4

5
    if (!ptr)
6
        ptr = malloc(9);
7

8
    if (ptr)
9
        strcpy(ptr, "testwert");
10

11
    return ptr;
12
}

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
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.