Dangling Pointers



  • DonnerCobra schrieb:

    Hi!

    Nicht ohne das du selbst das verwaltest.

    Wie genau meinst du das? Wie könnte ich das denn selbst verwalten?

    Zusatz: Irgendwo wird doch festgelegt ob das Objekt im Speicher freigegeben ist, oder nicht, oder vertu ich mich da?

    Bye

    Komplexe Betriebssysteme wissen zwar mehr oder weniger gut, welche Ressourcen von welchem Programm belegt werden, aber Standard-C++ Programme können ja für alle möglichen Plattformen übersetzt werden.
    Da es auch einen Haufen Plattformen gibt, wo der Speicher nicht von irgendwelchen Betriebssystemen überwacht wird, und Standardkonforme-C++-Programme auch dort laufen sollen, gibt es auch keine standardkonforme Möglichkeit für ein Programm sowas zu ermitteln. Du musste selbst verwalten, was von Dir belegt wurde.



  • Wie genau meinst du das? Wie könnte ich das denn selbst verwalten?

    Könntest eine Klasse schreiben der du mitteilst wenn du ein Objekt erstellst und löschst. Dann kann die prüfen ob der Pointer noch gültig ist.
    Oder nimmst auto_ptr oder sonstige smart pointer.

    Zusatz: Irgendwo wird doch festgelegt ob das Objekt im Speicher freigegeben ist, oder nicht, oder vertu ich mich da?

    Im Grunde passiert folgendes:

    a) du willst ein neues Objekt erstellen
    b) der Speicher reicht nicht
    c) das OS gibt deinem Programm mehr Speicher
    d) dein Programm sucht eine passende Stelle raus, notiert sich dies irgendwie
    e) und gibt dir einen Pointer zurück (ruft dann Konstruktor auf etc.)
    f) du löschst es
    g) Destruktor rödelt durch
    h) Programm markiert als frei
    i) OS läßt dem Programm den Speicher erst einmal

    Eine Möglichkeit h und d direkt abzufragen, wäre mir neu.
    Solange der Speicher zwar von deinem Programm freigegeben ist, sich das OS dies aber nicht zurückholt, kannst du theoretisch (was aber ungefähr mit Völkermord gleichzusetzen ist, wenn du Programmierer danach fragst) weiter auf dem Speicher arbeiten.



  • Foo* p = new Foo();
    delete p;
    is_dangling_ptr(p); //ja
    Bar* p2=new Bar();
    is_dangling_ptr(p); //nein, da Bar an der Stelle von Foo steht, aber eigentlich doch wild, da wir ja ein Foo Objekt dort erwarten würden, oder?



  • Ging ja nur darum ob die Speicherstelle freigegeben ist. 😃
    Aber recht hast du. 😉



  • DonnerCobra schrieb:

    Gibt es eine Möglichkeit herauszufinden, ob eine Speicherstelle freigegeben ist, oder nicht?

    Einige Memory-Manager, z.B. FastMM, sind im Debug-Modus in der Lage, so etwas festzustellen; auch Debugging-Tools wie CodeGuard können wilde Zeiger erkennen.

    Unter Windows gibt es außerdem die IsBadxxxPtr-Funktionen.



  • audacia: Auch in der Release version letztlich?

    Danke 🙂



  • DonnerCobra schrieb:

    audacia: Auch in der Release version letztlich?

    ja, aber lies meinen beitrag vorher



  • DonnerCobra schrieb:

    Gibt es eine Möglichkeit herauszufinden, ob eine Speicherstelle freigegeben ist, oder nicht?

    Wie schon vorher beantwortet, nein.

    Die erwähnten Smartpointer können hier eine Option sein, ich beziehe mich hierbei auf die Kombination shared_ptr / weak_ptr (Boost und std::tr1).

    cu André



  • DonnerCobra schrieb:

    audacia: Auch in der Release version letztlich?

    Du hast die Seite, die ich verlinkt habe, gelesen?

    Wie du der Diskussion eigentlich entnehmen hättest können, ist so etwas zwar zu Debugging-Zwecken machbar, jedoch im praktischen Einsatz schlichtweg ein Designfehler.

    Raymond Chen schrieb:

    "But what should I do, then, if somebody passes me a bad pointer?"

    You should crash.

    No, really.



  • Wobei man den "PointerManager" auch über Templates lösen könnte, so daß jede Klasse seinen eigenen hat, so daß sichergestellt werden kann das ein Pointer auch wirklich auf ein Objekt einer bestimmten Klasse zeigt. Bei Vererbung etc. natürlich unpraktisch und überhaupt nicht die feine Art, funzt aber.

    Wobei "funzt aber" einen eigentlich aufhorchen lassen sollte. 😉



  • Fellhuhn schrieb:

    Wobei man den "PointerManager" auch über Templates lösen könnte, so daß jede Klasse seinen eigenen hat, so daß sichergestellt werden kann das ein Pointer auch wirklich auf ein Objekt einer bestimmten Klasse zeigt. Bei Vererbung etc. natürlich unpraktisch und überhaupt nicht die feine Art, funzt aber.

    Wobei "funzt aber" einen eigentlich aufhorchen lassen sollte. 😉

    wie willst du das mit vererbten klassen lösen?
    und selbst wenn: geschwister sind nicht kompatibel haben aber die selbe base. sehr kompliziert das ganze.

    weiters hat man das problem mit zerstörten objekten die noch nicht den speicher zurück gegeben haben.

    und bei stack objekten geht es auch nicht.



  • Shade Of Mine schrieb:

    wie willst du das mit vererbten klassen lösen?
    und selbst wenn: geschwister sind nicht kompatibel haben aber die selbe base. sehr kompliziert das ganze.

    Vererbung ist dabei ein Problem, ja.

    weiters hat man das problem mit zerstörten objekten die noch nicht den speicher zurück gegeben haben.

    Das wäre in dem Falle ja egal. Wenn man in dem Moment wo man ein Objekt per delete löscht ihn aus dem Speichermanager entfernt, gilt der Zeiger als ungültig. Es geht ja nicht darum, ob der Speicher wirklich schon freigegeben wurde.

    und bei stack objekten geht es auch nicht.

    Pointer auf Stack-Objekte? Die Pointer sollten eigentlich den gleichen Scope haben wie die Objekte selbst, sonst wird es eh sehr schnell sehr ungemütlich.



  • Fellhuhn schrieb:

    weiters hat man das problem mit zerstörten objekten die noch nicht den speicher zurück gegeben haben.

    Das wäre in dem Falle ja egal. Wenn man in dem Moment wo man ein Objekt per delete löscht ihn aus dem Speichermanager entfernt, gilt der Zeiger als ungültig. Es geht ja nicht darum, ob der Speicher wirklich schon freigegeben wurde.

    Ich kann objekte zerstören und erstellen wie ich lustig bin.

    ohne dass der speicher manager etwas mitbekommt. schau dir std::vector einmal an. der holt sich mehr speicher als er braucht und erstellt und zerstört darin die objekte wie er lustig ist.

    und er holt den speicher über ::operator new und geht somit komplett an jedem system dass du dir ausdenken kannst vorbei.

    und bei stack objekten geht es auch nicht.

    Pointer auf Stack-Objekte? Die Pointer sollten eigentlich den gleichen Scope haben wie die Objekte selbst, sonst wird es eh sehr schnell sehr ungemütlich.

    es sollte auch keine dangling pointers geben, sonst wird es sehr schnell sehr ungemütlich. der punkt aber ist: so ein system wie du es dir vorstellst ist nicht mal halbwegs vernünftig implementierbar. man kann nur ganz wenige spezialfälle abdecken - aber es scheitert bereits an einem einfachen std::vector.



  • es sollte auch keine dangling pointers geben, sonst wird es sehr schnell sehr ungemütlich. der punkt aber ist: so ein system wie du es dir vorstellst ist nicht mal halbwegs vernünftig implementierbar. man kann nur ganz wenige spezialfälle abdecken - aber es scheitert bereits an einem einfachen std::vector.

    Ging ja auch nicht um die Eierlegende Wollmilchsau, sondern darum seinen eigenen Kram zu verwalten. Ob das nun funktioniert in dem Anwendungsfall oder überhaupt Sinn macht, kann wohl kaum jemand sagen, da wir ja nicht einmal wissen was er vorhat.



  • Shade Of Mine schrieb:

    und er holt den speicher über ::operator new und geht somit komplett an jedem system dass du dir ausdenken kannst vorbei.

    Was ist mit der Überladung des new -Operators?



  • Nexus schrieb:

    Shade Of Mine schrieb:

    und er holt den speicher über ::operator new und geht somit komplett an jedem system dass du dir ausdenken kannst vorbei.

    Was ist mit der Überladung des new -Operators?

    ::operator new bekommt nur die anforderung: allokiere mir X Bytes.
    welche sinnvollen daten willst du daraus ableiten?



  • Man könnte doch eine Klasse schreiben, die jedesmal bei new -Aufrufen informiert wird und sich dann den belegten Speicherbereich merkt (von mir aus in einem dynamischen Array mit malloc() ). Bei delete wird dann geprüft, ob der Bereich gültig ist.

    Ich hab sogar schon selber mal was ähnliches geschrieben, natürlich noch nicht ausgereift...



  • Nexus schrieb:

    Man könnte doch eine Klasse schreiben, die jedesmal bei new -Aufrufen informiert wird und sich dann den belegten Speicherbereich merkt (von mir aus in einem dynamischen Array mit malloc() ). Bei delete wird dann geprüft, ob der Bereich gültig ist.

    Und welche Information hast du dann?
    Dann kann man gleich IsBad?Ptr nehmen. Die information bringt dir nämlich nichts. Du kannst nur sagen ob der Speicher allokiert ist oder nicht.

    Du weisst nicht ob dort ein Objekt lebt und welchen Typ es hat.



  • Ah sorry, dann hab ich die Fragestellung falsch verstanden. Ich bezog mich nämlich auf:

    DonnerCobra schrieb:

    Gibt es eine Möglichkeit herauszufinden, ob eine Speicherstelle freigegeben ist, oder nicht?

    Aber das Beispiel von dir vorher könnte man doch trotzdem (einfach sehr umständlich) behandeln, indem man Speicherbereiche noch nach der Freigabe überwacht...?



  • Nexus schrieb:

    Ah sorry, dann hab ich die Fragestellung falsch verstanden. Ich bezog mich nämlich auf:

    DonnerCobra schrieb:

    Gibt es eine Möglichkeit herauszufinden, ob eine Speicherstelle freigegeben ist, oder nicht?

    Aber das Beispiel von dir vorher könnte man doch trotzdem (einfach sehr umständlich) behandeln, indem man Speicherbereiche noch nach der Freigabe überwacht...?

    inwiefern überwachen?

    der OP spricht zwar von freigegeben aber in seinem beispiel und in seinem text spricht er von der erkennung von dangling pointers und das ist eben nicht möglich. für alles andere gibt es IsBad?Ptr


Anmelden zum Antworten