Forum: PC-Programmierung C pointer frage


von guest (Gast)


Lesenswert?

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ß

von Vlad T. (vlad_tepesch)


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.

von Vlad T. (vlad_tepesch)


Lesenswert?

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.

von guest (Gast)


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ß

von der mechatroniker (Gast)


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

von Horst (Gast)


Lesenswert?

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.

von Andreas F. (aferber)


Lesenswert?

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

von Karl H. (kbuchegg)


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.

von Andreas F. (aferber)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.