amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > C++ Problem: Objektfreigabe [ - Suche - Neue Beiträge - Registrieren - Login - ]

1 -2- [ - Beitrag schreiben - ]

28.10.2004, 18:40 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Reth:
Ich hab Objektvariablen LinkedListC<Typ> liste; im HeaderFile bei der Objektdefinition angelegt und deren Destruktoren werden beim Beenden des Programmes anscheinend nicht gerufen.


Abgesehen davon, dass globale Variablen keine gute Idee sind, sollte trotzdem der Destruktor korrekt aufgerufen werden. Wenn das nicht passiert, fallen mir zwei Möglichkeiten ein:
  • Du beendest das Programm nicht korrekt (hinter dem Rücken des Compilers
  • Der Compiler ist fehlerhaft

    mfg
    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ - Antworten - Zitieren - Direktlink - ]

  • 28.10.2004, 22:45 Uhr

    Reth
    Posts: 1858
    Nutzer
    Zitat:
    Original von Holger:

    Abgesehen davon, dass globale Variablen keine gute Idee sind, sollte trotzdem der Destruktor korrekt aufgerufen werden. Wenn das nicht passiert, fallen mir zwei Möglichkeiten ein:
  • Du beendest das Programm nicht korrekt (hinter dem Rücken des Compilers
  • Der Compiler ist fehlerhaft

  • Aber wie sieht dann die richtige Freigabe syntaktisch aus?
    ich habs mit liste.~LinkedListC<Typ>(); probiert (und Varianten). Immer erfolglos.

    Was wäre denn die Alternative zu globalen Variablen innerhalb einer Klasse? Schien mir der beste Weg und mache ich auch immer, wenn ich ne Variable innerhalb mehrerer Methoden einer Klasse brauche, sonst müsste ich sie ja jedesmal bei jedem Methodenaufruf übergeben?!

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 00:02 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von Reth:
    Aber wie sieht dann die richtige Freigabe syntaktisch aus?
    ich habs mit liste.~LinkedListC<Typ>(); probiert (und Varianten). Immer erfolglos.

    Was wäre denn die Alternative zu globalen Variablen innerhalb einer Klasse? Schien mir der beste Weg und mache ich auch immer, wenn ich ne Variable innerhalb mehrerer Methoden einer Klasse brauche, sonst müsste ich sie ja jedesmal bei jedem Methodenaufruf übergeben?!

    Um Himmels Willen, was schmeißt Du denn hier durcheinander!
    Nochmal: Im Normallfall wird der Destruktor automatisch aufgerufen.
    Und zwar wenn der Gültigkeitsbereich verlassen wird. Globale Variablen sind die, die außerhalb von allem stehen, die sind somit die gesamte Programmlaufzeit gültig.
    Variablen, die in einer Klasse definiert werden, sind normalerweise Instanzvariablen und somit genausolange gültig, wie das jeweilige Objekt, zu dem sie gehören.
    Dann gibt es natürlich noch die lokalen Variablen innerhalb einer Funktion/Methode, und wenn man auf globale Variablen verzichtet, steckt jedes Objekt entweder direkt oder indirekt in einer lokalen Variablen.
    Das war jetzt etwas vereinfacht, aber wenn es dabei schon hakt, solltest Du auf jeden Fall nochmal einen Schritt zurück machen und Dich mit den Grundlagen beschäftigen.

    Ganz simpel:
    code:
    void aMethod()
    {
      Foo var(0, 1); // <- Konstruktor
      //...
    
      {
        Foo var2(2, 3); // <- Konstruktor
        //...
    
      } //<- Destruktor var2
    
    } // <- Destruktor var


    mfg
    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 00:33 Uhr

    Reth
    Posts: 1858
    Nutzer
    Hallo Holger,

    an den Grundlagen hakt es eigentlich nicht.Ich weiss (von Javaseite her) welche Variablen in welchem Scope Gültigkeit besitzen. Nach alldem was ich über C++ erfahren habe, wusste ich auch, was Du mir nochmals gesagt hast: Wenn ein Gültigkeitsbereich eines Objektes verlassen wird, wird dessen Destruktor automatisch gerufen.

    Naachdem das aber bei meinen Objekten nicht geschah, dachte ich dass ich evtl. in einigen Fällen Destruktoren manuell rufen muss!?

    Darum dieses seltsame Konstrukt was einem auch nur die Haare zu Berge stehen lassen kann.

    Aber dann muss ich weiter Debuggen, dann liegt bei mir das Problem noch an anderer Stelle, so dass deswegen die Destruktoren nicht gerufen werden.

    Die Objekte selbst sind mit new angelegt und liegen in ebenfalls mit new angelegten Wrappern.

    Ein new verlangt doch aber immer nach einem delete, oder werden mit new angelegte Objekte auch beim Verlassen des Gültigkeitsbereiches automatisch gelöscht?

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 00:39 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von Reth:
    Ein new verlangt doch aber immer nach einem delete, oder werden mit new angelegte Objekte auch beim Verlassen des Gültigkeitsbereiches automatisch gelöscht?

    Natürlich muß Du delete benutzten, was sollte denn sonst der Gültigkeitsbereich sein?

    mfg
    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 01:02 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von Reth:
    Die Objekte selbst sind mit new angelegt und liegen in ebenfalls mit new angelegten Wrappern.


    Da fällt mir doch etwas auf. Hast Du möglicherweise als "verwöhnter Javaprogrammierer" nicht bedacht, daß Methodenaufrufe in C++ per default nicht dynamisch sind?

    Bei diesem Code:
    code:
    #include <iostream>
    
    class A
    {
    public:
      A()  {}
      ~A() {}
    };
    
    class B: public A
    {
    public:
      B()  {}
      ~B() {}
    };
    
    int main(int n, char**a)
    {
      A* ptr=new B();
      delete ptr;
    }

    wird ~B() nicht aufgerufen, da der statische typ von ptr "Pointer auf A" ist. Der Destruktor muß in dieser Konstellation als dynamisch deklariert werden:
    code:
    #include <iostream>
    
    class A
    {
    public:
      A() {}
      virtual ~A() {}
    };
    
    class B: public A
    {
    public:
      B()  {}
      ~B() {}
    };
    
    int main(int n, char**a)
    {
      A* ptr=new B();
      delete ptr;
    }

    Dann werden korrekt ~B() und ~A() aufgerufen.
    Es reicht, wenn er in der Basisklasse als dynamisch deklariert ist.

    mfg
    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ Dieser Beitrag wurde von Holger am 29.10.2004 editiert. ]

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 01:13 Uhr

    Reth
    Posts: 1858
    Nutzer
    @Holger

    Nein das war mir so noch nicht klar! Vielen Dank. Muss meinen Code daraufhin noch untersuchen.

    Momentan bin ich in der Freigabeproblematik schon ein ganzes Stück weiter aber auch an ner Privilege Violation angelangt, die ich erstmal finden muss!

    Ich hätte übrigens als Vorschlag zur automatischen Freigabe von mit new angelegten Objekten das Programmende als Ende des Gültigkeitsbereiches gehabt.

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 08:18 Uhr

    Solar
    Posts: 3680
    Nutzer
    Zitat:
    Aber wie sieht dann die richtige Freigabe syntaktisch aus?
    ich habs mit liste.~LinkedListC<Typ>(); probiert (und Varianten).


    Also, auf den Teil mit <Typ> wäre ich nicht gekommen... liste.~LinkedListC(), wenn überhaupt. ;)

    Ich weiß aber nicht, ob das geht, denn man ruft einen Destruktor nicht explizit auf... entweder geht eine automatische Variable out-of-scope, oder man ruft delete(). Alles andere ist ein semantisches Verbrechen. ;)

    Zitat:
    Was wäre denn die Alternative zu globalen Variablen innerhalb einer Klasse?

    Was, wie, wer? Innerhalb einer Klasse? Was, um Himmels willen, treibst Du da? Eine Variable ist entweder global, oder Member einer Klasse...?!?!?

    Zitat:
    Schien mir der beste Weg und mache ich auch immer, wenn ich ne Variable innerhalb mehrerer Methoden einer Klasse brauche, sonst müsste ich sie ja jedesmal bei jedem Methodenaufruf übergeben?!

    Öh... Du meinst nicht zufällig eine statische Membervariable?

    code:
    class MyClass
    {
        public:
            MyClass();
    
        private:
            int mInstanceInt;
            static int mClassInt;
    };


    Hier hat jede Instanz von MyClass ein eigenes mInstanceInt, aber alle Instanzen von MyClass haben nur ein gemeinsames mClassInt.

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 11:15 Uhr

    MrMarco
    Posts: 445
    Nutzer
    Der Thread gefällt mir. :)

    Hier bekommt man in Kurzform jeden Bockmist vorgeführt, den man verbrechen kann und gleich gesagt wie man es besser macht :)

    /me das C++ Buch weglegt und hier mitließt. Macht mehr Fun :)

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 11:31 Uhr

    Reth
    Posts: 1858
    Nutzer
    Zitat:
    Original von Solar:
    Zitat:
    Was wäre denn die Alternative zu globalen Variablen innerhalb einer Klasse?

    Was, wie, wer? Innerhalb einer Klasse? Was, um Himmels willen, treibst Du da? Eine Variable ist entweder global, oder Member einer Klasse...?!?!?


    Alsodas ist nicht auf meinem Mist gewachsen! Holger hat mit globalen Variablen angefangen, indem er auf meine Klassenvariablen einging. Ich kenne den Unterschied zwischen Klassenmembern und globalen Variablen, hab nur direkt auf Holgers antwort gepostet und wollte keinen neuen Begriff einführen, damit wir vom selben reden.

    Zitat:
    Öh... Du meinst nicht zufällig eine statische Membervariable?

    Njet! Ich meine schon Klassenmembers wie in Deinem unteren Bsp. Der Sinn dieser Variablen besteht nun einmal darin, dass jedes Objekt eine eigene Instanz dieser Variablen hat (nur wenn sie als statisch deklariert wurde nicht, jedenfalls nicht in Java und laut Deinem Bsp. wohl auch nicht in C++) und dass die Variable innerhalb des Objektes überall verfügbar ist.

    Holgers Antwort entnahm ich, dass das wohl in C++ eher unüblich sei (benutze es in Java ständig so, da ich es sinnvoll finde). Darum hab ich nochmal nachgefragt!

    Was Du in Deinem Bsp. angegeben hast, kannte ich seitens Java schon seit Jahren. Hätte mich sehr erstaunt, wenn es in C++ anders wäre.

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 11:50 Uhr

    Reth
    Posts: 1858
    Nutzer
    Zitat:
    Original von MrMarco:
    Der Thread gefällt mir. :)

    Hier bekommt man in Kurzform jeden Bockmist vorgeführt, den man verbrechen kann und gleich gesagt wie man es besser macht :)

    /me das C++ Buch weglegt und hier mitließt. Macht mehr Fun :)


    Toll, dass ich zur Erheiterung beitragen konnte. :angry:

    Jetzt denk ich bald selbst, dass ich in meinem Leben noch nie ein Stück Code fertigbekommen hab, was auch läuft! :(

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 11:57 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von Reth:
    Holgers Antwort entnahm ich, dass das wohl in C++ eher unüblich sei (benutze es in Java ständig so, da ich es sinnvoll finde). Darum hab ich nochmal nachgefragt!

    Das lag nur daran, daß Du betont hast, daß die Variable in einem Header-File definiert wird. Das hat den Eindruck erweckt, es würde sich um eine globale Variable handeln, was offenbar nicht der Fall ist. Instanz-Variablen sind dann out-of-scope, wenn die entsprechende Instanz out-of-scope ist.
    Ich vermute mal, es handelt sich dann eher um die pointer-Problematik.

    mfg
    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 12:03 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von Reth:
    Toll, dass ich zur Erheiterung beitragen konnte. :angry:

    Jetzt denk ich bald selbst, dass ich in meinem Leben noch nie ein Stück Code fertigbekommen hab, was auch läuft! :(

    Leg das nicht auf die Goldwaage. Java und C++ sind zwei völlig unterschiedliche Programmiersprachen, die aber dummerweise optisch ähnlich aussehen. Ist vermutlich wie Holländisch lernen. Klingt alles so vertraut und ist dann doch was völlig anderes. :D
    Diese Probleme gibt es in beide Richtungen, wobei ich meist das Gefühl habe, das Java-Programmierer, die mal was mit C++ machen müssen eher "Ich kapier das nicht" und während C++-Programmierer "Java ist Scheiße" sagen. Nur so ein Gefühl...

    mfg
    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 12:34 Uhr

    Reth
    Posts: 1858
    Nutzer
    Zitat:
    Original von Holger:
    Leg das nicht auf die Goldwaage.


    Keine Angst.
    Ich merk ja selbst, dass ich in dem Thread etwas unfähig rüber komme.
    Aber hab mit C++ auch erst angefangen und momentan ein massives Problem aufgrund der Freigaben etc., was immer zum Absturz führt!

    Drum vielen Dank an euch alle für die bisherigen Hilfen!

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 12:37 Uhr

    MrMarco
    Posts: 445
    Nutzer
    Zitat:
    Original von Reth:
    Zitat:
    Original von MrMarco:
    Der Thread gefällt mir. :)

    Hier bekommt man in Kurzform jeden Bockmist vorgeführt, den man verbrechen kann und gleich gesagt wie man es besser macht :)

    /me das C++ Buch weglegt und hier mitließt. Macht mehr Fun :)


    Toll, dass ich zur Erheiterung beitragen konnte. :angry:

    Jetzt denk ich bald selbst, dass ich in meinem Leben noch nie ein Stück Code fertigbekommen hab, was auch läuft! :(


    Nanana... so war das jetzt aber nicht gemeint. Frag mal Solar was ich öfters für einen Bockmist baue. Der könnte dir gerade heute wieder eine Story erzählen, wo du mit dem Kopf gegen die Wand hämmern würdest.

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 13:10 Uhr

    Solar
    Posts: 3680
    Nutzer
    Niemand ist fehlerfrei; ich hab' ja mit auto_ptr weiter oben auch einen größeren Bock geschossen. Für meinen Teil ist dieser Thread die Gelegenheit, mich mal wieder genauer mit Destruktoren auseinanderzusetzen, denn in den drei Jahren beruflicher C++-Entwicklung habe ich noch keinen einzigen Destruktor schreiben müssen. Ich bin also selber etwas eingerostet. ;)

    Kommen wir also zurück zum eigentlichen Thema. ;)

    Zitat:
    Original von Reth:

    Ich meine schon Klassenmembers wie in Deinem unteren Bsp. Der Sinn dieser Variablen besteht nun einmal darin, dass jedes Objekt eine eigene Instanz dieser Variablen hat (nur wenn sie als statisch deklariert wurde nicht, jedenfalls nicht in Java und laut Deinem Bsp. wohl auch nicht in C++) und dass die Variable innerhalb des Objektes überall verfügbar ist.

    Holgers Antwort entnahm ich, dass das wohl in C++ eher unüblich sei (benutze es in Java ständig so, da ich es sinnvoll finde). Darum hab ich nochmal nachgefragt!


    Falls Du stinknormale Membervariablen meinst, die sind in C++ genauso üblich wie in Java. (Welches Statement von Holger hast Du denn so interpretiert, daß dem nicht so wäre?)

    Zitat:
    Was Du in Deinem Bsp. angegeben hast, kannte ich seitens Java schon seit Jahren. Hätte mich sehr erstaunt, wenn es in C++ anders wäre.

    Man weiß ja nie. ;-)

    Also: Die Destruktoren von Membervariablen werden beim Zerstören der Objektinstanz - entweder durch out-of-scope-gehen einer automatischen Variablen oder delete() auf den Pointer - automatisch aufgerufen.

    Wieso das bei Dir nicht so sein sollte, ist ohne Einblick in den Code etwas schwierig...

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 19:38 Uhr

    Reth
    Posts: 1858
    Nutzer
    Zitat:
    Original von MrMarco:
    Nanana... so war das jetzt aber nicht gemeint. Frag mal Solar was ich öfters für einen Bockmist baue. Der könnte dir gerade heute wieder eine Story erzählen, wo du mit dem Kopf gegen die Wand hämmern würdest.


    Keine Sorge, bin niemandem böse. Ich habe selbst schon viel aus anderen Threads gelernt! Dafür sind sie ja gedacht und jede Frage wurde/wird mal gestellt! :)

    [ - Antworten - Zitieren - Direktlink - ]

    29.10.2004, 19:51 Uhr

    Reth
    Posts: 1858
    Nutzer
    Zitat:
    Original von Solar:
    Niemand ist fehlerfrei;


    Kein Problem. Ich am wenigsten.

    Zitat:
    Also: Die Destruktoren von Membervariablen werden beim Zerstören der Objektinstanz - entweder durch out-of-scope-gehen einer automatischen Variablen oder delete() auf den Pointer - automatisch aufgerufen.

    Wieso das bei Dir nicht so sein sollte, ist ohne Einblick in den Code etwas schwierig...



    Hab mich diesbezüglich glücklicherweise geirrt. Die Destruktoren werden gerufen, allerdings stimmt die Reihenfolge für meine Zwecke wohl nicht.

    Andere Membervariablen hab ich als Zeiger angelegt und die Objekte mit new() erzeugt. So kann ich auch ihre Auflösung mit delete() bestimmen. Im Destruktor der Hauptklasse wird die Aufräummethode gerufen und diese schliesst das Fenster und den Screen. Davor werden mit delete() meine Member freigegeben.

    Und erst dann ganz am Schluss wird der Destruktor der Membervariablen gerufen, die nicht als Zeiger angelegt ist. In dieser (ist so ne Liste) werden dann meine grafischen Objekte freigegeben, die ihrerseits BitMaps freigeben.
    Dabei kommt es nach einigen solcher freigegebenen Objekte zur genannten Privileg Verletzung. Weiss noch nicht wieso.Evtl. weil das Fenster mit dem RastPort und der von diesem entnommenen FriendBitMap (Zeiger) nicht mehr existieren?

    Mein erster Gedanke ist nun dieses Member auch als Zeiger anzulegen, mit new() zu erstellen und mit delete() vorm Schliessen des Fensters aufzulösen. Vielleicht hilfts.

    Denke mal, dass ich bedingt durch new() und die Listen noch einige Speicherlecks haben könnte. Werde ich prüfen,wenn ich die Privileg Verletzung gefunden hab.

    [ - Antworten - Zitieren - Direktlink - ]

    29.01.2005, 23:00 Uhr

    Reth
    Posts: 1858
    Nutzer
    @solar, holger & co.

    Ich hoffe, ihr lest hier wieder rein!

    Hab noch mal ne Frage zu den eingangs erwähnten lokalen Objekten, die man in Methoden anlegen kann:

    A Klasse:Methode(Param)
    {
    A var = "Hallo!";
    return A;
    }


    Wie sieht es mit dem Destruktor von A aus? Wann wird der gerufen?
    Wenn diese Methode hier verlassen wird, oder die aufrufende (falls dort die von obiger Methode erhaltene Variable nicht anderweitig weitergegeben wird)?

    Danke schon mal
    Ciao

    [ - Antworten - Zitieren - Direktlink - ]

    30.01.2005, 01:28 Uhr

    Holger
    Posts: 8116
    Nutzer
    Zitat:
    Original von Reth:
    Wie sieht es mit dem Destruktor von A aus? Wann wird der gerufen?
    Wenn diese Methode hier verlassen wird, oder die aufrufende (falls dort die von obiger Methode erhaltene Variable nicht anderweitig weitergegeben wird)?

    Ich kann jetzt nichts mit hundertprozentiger Sicherheit sagen, aber soviel ich weiß, hängt das auch davon ab, wie Du das Objekt in der aufrufenden Methode behandelst. Wenn Du es zum Beispiel einer Variablen (nicht als Referenz) zuweist, wird ein neues Objekt über den Kopierkonstruktor angelegt und das alte danach zerstört.
    Ich glaube, es ist grundsätzlich besser, das Objekt als Referenz (A) zurückzugeben, aber da soll sich ruhig ein C++-Experte zu äußern, ich bin nämlich keiner.

    mfg
    --
    Good coders do not comment. What was hard to write should be hard to read too.

    [ Dieser Beitrag wurde von Holger am 30.01.2005 editiert. ]

    [ - Antworten - Zitieren - Direktlink - ]


    1 -2- [ - Beitrag schreiben - ]


    amiga-news.de Forum > Programmierung > C++ Problem: Objektfreigabe [ - Suche - Neue Beiträge - Registrieren - Login - ]


    .
    Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
    Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
    .