Funktionen und Zeiger

  • Hallo!

    Wenn ich eine funktion1 habe, welche mir einen zeiger zurückgibt.. (welcher in der funktion1 dynamisch erzeugt wurde...) und ich nun diese funktion in einer funktion2 aufrufe, welche diesen zurückgibt, muss ich dann den zeiger speicherplatz der funktion1 freigeben? oder bin ich total am falschen weg? malloc erstellt doch eine variable, die über die funktion, hinaus lebt. wenn ich nun einen zeiger deklariere, über malloc, wird doch sowohl für das objekt auf das gezeigt wird, speicher reserviert, als auch dem zeiger selbst, welcher auf dieses objekt zeigt.

    funktion 1;

    int * funktion1(){

    int * rückgabewert1;
    rückgabewert1 = malloc(sizeof(int);

    int = blablabla;

    return int;
    }

    int * funktion2(){


    int * rückgabewert2;
    rückgabewert2 = malloc(sizeof(int);


    rückgabewert2 = (int*) funktion1();

    return funktion2;

    }

    frage: was ist mit dem zeiger der funktion1? der lebt doch noch, aber zugreifen könnte man nicht mehr..oder?

  • reparier bitte (wiedermal) alle variablennamen, damit man weiss was du meinst :)

    [font=verdana,sans-serif]"An über-programmer is likely to be someone who stares quietly into space and then says 'Hmm. I think I've seen something like this before.'" -- John D. Cock[/font]

    opentu.net - freier, unzensierter Informationsaustausch via IRC-Channel!
    Hilfe und Support in Studienangelegenheiten, gemütliches Beisammensein, von und mit Leuten aus dem Informatik-Forum!

  • reparieren? vielleicht sollte ich meine frage einfach verbal beschreiben:

    in einer funktion bekomme ich einen dynamischen zeiger als rückgabewert. dieser zeiger zeigt eben auf das dynamisch erzeugte objekt. ich muss es dynamisch erzeugen, da er ja sonst, nach dem ende der funktion, nicht mehr vernünftig existieren würde (außer im stack)

    in einer zweiten funktion rufe ich meine erste funktion auf, "übernehme" den zeiger und will ihn jetzt aus der funktion 2 zurückgeben. müsste ich dann icht auch zusätzlich ein dynamisches objekt erzeugen (malloc zeiger) welcher auf das selbe objekt wie der zeiger der funktion eins zeigt?

  • nein, in der 2. funktion brauchst du kein malloc mehr.
    hast du einmal den speicher mit malloc reserviert beleibt dieser so lange erhalten bis mit free wieder freigegeben wird, oder bis das programm beendet wird.

    in deinem beispiel hättest du ein speicher-leck:

    rückgabewert2 = malloc(sizeof(int);
    ... hier reservierst du zum ersten mal speicher, und "rückgabewert2" beinhaltet den zeiger auf diesen speicher.

    rückgabewert2 = (int*) funktion1();
    ... hier reserviert "funktion1()" zum 2. mal speicher, "rückgabewert2" wird mit dem zeiger auf den 2. speicher überschrieben. der zuerst reservierte speicher ist immer noch vorhanden, nur der zeiger mit dem du darauf zugreifen könntest ist weg.

  • ich versteh echt nicht, wieso so viele leute probleme haben mit pointern...

    Stell dir vor, du hast einen Block Speicher. Der ist durchnummeriert von 0 bis 0xFFFF. Wenn du malloc aufrufst, sucht es der in der Speicherzuordnungsliste nach einem durchgehenden Teil mit der als malloc-Parameter angegebenen Größe in diesem Speicher, der noch *nicht* in der Liste steht. Dann trägt malloc die Startadresse und Länge in die Liste ein, und returnt die Startadresse (das ist nix anderes als eine Zahl zwischen 0 und 0xFFFF!).
    Dieser Speicherbereich ist jetzt dein, du kannst darin machen was du willst. Wenn du free() aufrufst, sucht diese Funktion einen Eintrag mit der von dir angegebenen Startadresse (wieder Hinweis: das ist eine Zahl zwischen 0 und 0xFFFF).
    Wenn du jetzt malloc aufrufst, und diese Zahl lokal speicherst, kannst du eben auf deinen Speicherbereich zugreifen (weil du ja die Adresse kennst). Wenn du jetzt den Wert überspeicherst, weißt du nicht mehr, wo dein anderer Block war (nennt sich dann Leak).

    [font=verdana,sans-serif]"An über-programmer is likely to be someone who stares quietly into space and then says 'Hmm. I think I've seen something like this before.'" -- John D. Cock[/font]

    opentu.net - freier, unzensierter Informationsaustausch via IRC-Channel!
    Hilfe und Support in Studienangelegenheiten, gemütliches Beisammensein, von und mit Leuten aus dem Informatik-Forum!

  • danke! das problem der pointer ist ja nicht, dass mir diese dynamische speicherallozierung nicht klar wäre. es geht darum, dass ich nicht weiß/wusste, ob, wenn speicher alloziiert wird, dies nur für das objekt geschieht, auf das gezeigt wird (also ob speicher nur für das objekt reserviert wird) ODER auch für den POINTER. ein pointer besteht ja selbst aus einer adresse und einer adresse, auf die er verweist.

    nun dachte ich, wenn ich das objekt über free() freigebe, ich auch den pointer freigeben muss.

    aber anscheinend geht es hier nur um adressen ;)

    -> wenn ich also ein objekt dyn. erzeuge, hab ich seine adresse. diese adresse kann ich jetzt beliebig über funktionen mit pointern weiter (bzw zurückgeben) - OHNE das ich meine neuen pointer mit malloc iniitieren muss. da sie alle schon auf das das eine objekt zeigen.

    -> und damit wirklich nichts schief geht, übergebe ich einfach bei unterschiedlichen pointern NUR die adresse auf das OBJEKT, NICHT die adresse der pointer. (weil die ja, wenn sie nicht über malloc erzeugt werden) nach der funktion ihren geist aufgeben..

    richtig?

  • ja so ist es.

    stell dir einen pointer als int-wert vor in dem einfach die startadresse des reservierten speichers drinnen steht. übergibst du einer funktion einen pointer (bzw. gibt eine funktion einen pointer zurück) wird für diesen pointer ein "call by value" gemacht, d.h. die adresse die im pointer steht wird einfach in eine neue variable kopiert, welche automatisch wieder zerstört wird wenn die funktion (bzw. der block) verlassen wird.

  • Wie bereits von mir gesagt, ein pointer ist nur eine ZAHL und kann auch als solche behandelt werden (in C/C++ sogar mit addition, etc).

    [font=verdana,sans-serif]"An über-programmer is likely to be someone who stares quietly into space and then says 'Hmm. I think I've seen something like this before.'" -- John D. Cock[/font]

    opentu.net - freier, unzensierter Informationsaustausch via IRC-Channel!
    Hilfe und Support in Studienangelegenheiten, gemütliches Beisammensein, von und mit Leuten aus dem Informatik-Forum!

  • Im Übrigen würde ich diese Praxis (in funktion1() allozieren, vom Aufrufer freigeben) nicht unbedingt vorziehen. (Und das einmal ganz abgesehen davon, dass das Ersetzen von int durch int* nichts bringt, sondern eher nur für größere Objekte.)

    Also, rein vom guten Geschmack und der Durchsichtigkeit des Codes wegen würde ich solche Konstrukte vorziehen, die das Allozieren und Deallozieren auf der gleichen Ebene bewerkstelligen. Die Funktion selber würde dann einfach annehmen, dass der int-Pointer schon alloziert wurde, und im Idealfall brauchst du malloc() und free() gar nicht:


    Damit ersparst du dir potenizelle Memory-Leaks, die durch Vergessen von free() vorkommen würden, und hast außerdem eine Möglichkeit, eine "hat funktioniert oder nicht" Returnvariable zurückzugeben. Natürlich gibts trotzdem Fälle, in denen die Funktion selber allozieren sollte (z.B. das Abstract Factory design pattern), aber im Allgemeinen ist das ohne Garbage Collection wie in Java nicht unbedingt so eine tolle Idee.

    "Egbert B. Gebstadter is the Egbert B. Gebstadter of indirect self-reference." - Egbert B. Gebstadter

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!