Oh mein Gott! Ich habe Windows gekillt! ;-)



  • Sorry @ all.
    Hab mich vertan, war unter Win 95.



  • MAG schrieb:

    Grundsätzlich gilt bei der Verwendung von Zeigern:
    Nach dem Löschen immer NULL zuweisen:

    Mache ich nur, wenn der Zeiger selber state anzeigt. Also zB bei einem smartpointer, wenn zeiger==NULL wird auf nix gezeigt. aber normale zeiger (sofern ich sie mal roh anfassen sollte) setze ich nicht auf 0 - das versteckt das hoechstens fehler...



  • Nungut, irgendwie haben uns die letzten beiden Antworten aber bei der Lösung des Problems nicht wirklich weitergebracht - oder?

    @CSS

    Wäre wirklich gut wenn du endlich den Code postest! Oder sag einfach wenn du inzwischen kein Problem mehr hast.



  • Also es war wahrscheinlich so das ich unter Win 95 einen Zeiger auf den Reset-Schalter erlangen konnte. Diesen Zeiger habe ich dereferenziert und dann den Wert auf true gesetzt so das eine Strom floß und ein Reset durchgeführt wurde.

    Unter Win XP gab es nur einen sogenannten "Acess Violation".



  • Hi Shade Of Mine,

    Mache ich nur, wenn der Zeiger selber state anzeigt. Also zB bei einem smartpointer, wenn zeiger==NULL wird auf nix gezeigt. aber normale zeiger (sofern ich sie mal roh anfassen sollte) setze ich nicht auf 0 - das versteckt das hoechstens fehler...

    Und wenn der Zeiger von woanders referenziert wird hat dann keiner ne Chance mehr
    festzustellen ob der Zeiger (noch) gültig ist. 😮 😕

    mfg JJ



  • John Doe schrieb:

    Und wenn der Zeiger von woanders referenziert wird hat dann keiner ne Chance mehr
    festzustellen ob der Zeiger (noch) gültig ist. 😮 😕

    äh, man hat im Programm doch irgendeinen logischen Ablauf. Entweder es ist ein Zeiger der zugleich ein Flag ist, oder nicht.

    Einfach mal immer auf null setzen bzw. bei jedenm Zugriff auf null testen, ist ganz großer blödsinn.
    Man sollte sich schon im Klaren sein, was das Programm überhaupt tut.



  • Bei Programmen ab einer gewissen Grösse hab ich die Menge aller möglichen
    Abläufe (=Benutzerinteraktionen) jedenfalls nicht mehr im Kopf. Wenn du das kannst
    alle Achtung. (wofür brauchst du eigentlich einen Computer 😃 )

    Bei mir zumindest prüfen alle Funktionen die Zeiger übergeben bekommen diese auf
    Gültigkeit (!= 0). Im einfachsten Fall durch assert, dadurch finde ich definitiv
    frühzeitig Fehler. Dies gehört ausserdem zu den Codingvorgaben die in unserer
    Firma strikt vorgegeben sind und die auch persönlich für sinnvoll halte.

    mfg JJ



  • Das Überprüfen auf Null ist ja auch sinnvoll.

    Aber nicht das Null-Setzen. :p



  • Hey du Cleverle, wie willst du denn auf Null prüfen wenn du das Ding nach Verwendung nie wieder auf Null setzt. 😉

    Ausserdem, wer nach Gebrauch nicht wieder "aufräumt", wird Pointer vermutlich auch
    nicht mit NULL initialisieren, warum auch, den Ablauf des Programms hat man ja
    schliesslich im Kopf. 😃

    mfg JJ



  • Du machst also wirklich

    delete p;
    p = NULL;
    

    ? Wie peinlich...



  • John Doe schrieb:

    Bei Programmen ab einer gewissen Grösse hab ich die Menge aller möglichen
    Abläufe (=Benutzerinteraktionen) jedenfalls nicht mehr im Kopf. Wenn du das kannst
    alle Achtung. (wofür brauchst du eigentlich einen Computer 😃 )

    Deshalb haelt man variablen ganz lokal.
    da hast du vielleicht 10 Zeilen code die du ueberschauen musst, oder es ist eine Klassenvariable - dann muss man den Zweck der Klasse kennen.

    Alles in allem sollte man also schon wissen, was welche Variable macht.

    Bei mir zumindest prüfen alle Funktionen die Zeiger übergeben bekommen diese auf
    Gültigkeit (!= 0). Im einfachsten Fall durch assert, dadurch finde ich definitiv
    frühzeitig Fehler. Dies gehört ausserdem zu den Codingvorgaben die in unserer
    Firma strikt vorgegeben sind und die auch persönlich für sinnvoll halte.

    die frage ist halt immer, wieviel es bringt.
    ein

    foo* p=allocate();
    foo* p2=p;
    
    destroy(p2);
    p2=0;
    
    foobar(p);
    

    macht ja trotzdem Peng - das null setzen bringt sich also nur dann, wenn die Variable gleichzeitig ein Flag ist. Denn wenn sie kein flag ist, dann kille ich sie ja nicht einfach so, ohne das irgendwie erkenntlich zu machen. normalerweise wird der gueltigkeitsbereich der variable nach dem delete verlassen.

    das problem mit dem 0 setzen ist aber, dass mehrfache deletes (also krasse logikfehler) nicht auffallen.

    Zeiger 0 setzen ist also kein allheilmittel.



  • Mehrfaches deleten fällt nicht auf weils eben keine Problem ist.
    Wenn ichs nicht tue zerlegts mich irgendwann und irgendwo. Da find ich meinen
    Ansatz beruhigender. In einem Standardprodukt sollte man defensiv programmieren
    und Fehler schon im Ansatz vermeiden. Fehler beim Zugriff auf nicht mehr
    gültige Pointer dürfen gar nicht auftreten sondern müssen im Vorfeld bereits
    vermieden werden.

    Wenn deine Zeiger nur funktionslokal sind macht das wenig Sinn. Bei mir kommen
    aber durchaus Pointer als Membervariablen vor da behälts du nicht so einfach die
    Übersicht, vor allem wenn der Zugriff halt über GUI und Benutzereingaben erfolgt.

    mfg JJ



  • John Doe schrieb:

    Mehrfaches deleten fällt nicht auf weils eben keine Problem ist.

    Oh, es ist ein verdammt grosses problem. weil deine ablauf logik im arsch ist.
    sowas waere praktisch, wenn es beim debuggen auffaellt 😉

    du versuchst fehler zu verstecken, indem du die symptome abfaengst - das ist auf dauer nicht gut. denn der fehler ist ja da - auch wenn er sich nicht in einem absturz zeigt.

    Wenn ichs nicht tue zerlegts mich irgendwann und irgendwo.

    Nein, exakt beim 2. delete
    bzw. bei einem zugriff auf den zeiger (man kann ja problemlos debug allokatoren verwenden, somit sind solche Fehler kinderleicht zu finden (weil sie automatisch entdeckt werden).

    Nur kannst du bei einem NULL Zeiger nicht sagen, ob der Zeiger jetzt NULL oder wild ist - was ungut ist, weil es ja ein gravierender Unterschied ist.

    Da find ich meinen
    Ansatz beruhigender.

    Klar, du hast weniger abstuerze.
    aber bedenke: nur weil ein fehler (und gerade logikfehler koennen teuflisch sein) sich nicht bemerkbar macht, ist er trotzdem nicht fort.

    In einem Standardprodukt sollte man defensiv programmieren
    und Fehler schon im Ansatz vermeiden.

    Ja, vermeiden. nicht verstecken.

    Fehler beim Zugriff auf nicht mehr
    gültige Pointer dürfen gar nicht auftreten sondern müssen im Vorfeld bereits
    vermieden werden.

    Nein. nicht vermieden -> entdeckt.

    Wenn deine Zeiger nur funktionslokal sind macht das wenig Sinn. Bei mir kommen
    aber durchaus Pointer als Membervariablen vor da behälts du nicht so einfach die
    Übersicht, vor allem wenn der Zugriff halt über GUI und Benutzereingaben erfolgt.

    ??
    was hat ne GUI damit zu tun?
    wenn du dir unsicher bist, schreib halt immer einen kurzen kommentar, dass dieser zeiger ein flag ist.

    ich fuer meinen teil kann das selber ganz gut ueberblicken. denn kleine klassen sind recht uebersichtlich.

    wobei ich ja zeiger sowieso nur sehr ungerne roh anfasse - das problem also eigentlich garnicht habe, dass ein ungueltiger zeiger existiert.

    aber dennoch halte ich es fuer fragwuerdig fehler zu verstecken...
    delete 0;
    ist ja OK - aber
    delete wildptr;
    eben nicht.

    denn, wenn man einen wilden zeiger deleten will (den man ja schonmal geloescht hat) hat man einen gravierenden bug in der anwendung, der nicht auffaellt.

    anders ist die sache natuerlich wenn du sagst, dass alle zeiger ein flag sind. nur waere mir das zuviel aufwand fuer zuwenig nutzen...



  • Ich kann dir immer noch nicht ganz zustimmen 😃

    Wenn ich mehrfach n = 0 schreibe so zeugt das von Paranoia, stellt meines
    Erachtens aber keinen Fehler dar. Inbesondere geht dabei nicht schief. Ich
    verstecke also keinen Fehler sondern vermeide ihn. Wenn ich bei Benutzung
    mit assert abprüfe krieg ich auch definitiv raus ob ich da wo ich einen
    gültigen Pointer erwarte auch einen kriege oder ob ich da wo keinen (bereits)
    gültigen Pointer haben will versehentlich einen erhalte.

    Beispielsweise führen beispielsweise die MS COM-Smartpointer Klassen wie CComPtr
    automatisch genaus solche Prüfungen aus. Ich nehme mir übrigens nicht allzu oft
    MS als Vorbild 😃

    Alls besseres Vorbild halte ich mich dann doch an Steve McConnell "Code Complete"

    Set pointers to null after deleteing or freeing them...

    Übrigens tritt ein Fehler natürlich nicht erst beim zweiten Delete auf sondern
    bei jedem Zugriff auf den inzwischen ungültigen (und ungeprüften) Zugriff auf.

    mfg JJ



  • Also, ich bin auch ein 0-Setzer. Weiß auch nicht, was daran nicht richtig oder nicht gut sein soll? Bevor ich etwas instanziere, muß ich doch schauen, ob es nicht schon mal passiert ist. Dafür opfere ich gerne einen Taktzyklus, mehr kostet das heute bestimmt nicht...



  • Also irgendwie, stell ich mir deinen Code jetzt ziemlich chaotisch vor.

    Normalerweise legt man doch klar die Lebenszeit des Objekts fest. Wenn da mehrmals delete auf den selben Zeiger geht, ist das doch dann ein Logikfehler.
    Egal ob es im Programm zu einem Fehlverhalten kommt oder nicht. Es ist einfach was, dass man nicht haben will.

    du sagst, solche logikfehler sind nicht schlimm, solange das programm noch normal geht. Aber das ist doch ganz großer Mist. Irgendwann schreibt man vor's delete noch ein cout<<"Tschüss" oder etwas das nicht gleich auffällt und irgendwann knallts dann.
    Da lasse ich das Programm lieber beim falschen delete sofort abschmieren.



  • ich weiß nicht mehr wer das geschrieben hat aber Bluescreens können noch vorkommen hab selbst mal einen bei einem fatalen Fehler unabsichtlich ausgelöst



  • Ich setze nicht den Pointer auf 0 um möglichst oft ein delete drauf zumachen, 😃
    sondern um zu vermeiden das irgendwo in meinem Programm Pointer rumliegen von
    denen keiner weiss ob sie ungültig sind oder nicht.
    Für mich ist das genau der gleiche Automatismus mit dem ich Pointer auch mit
    0 initialisiere. Wenn ein Pointer 0 ist, dann ist er ungültig ansonsten ist er
    gültig. Wenn ein Program mehr als 100 nicht triviale Klassen enthält die ausserdem
    (oft) zueinander in Bezug stehen dann behälst auch du ganz sicher nicht den Überblick
    welcher Pointer zu einem bestimmten Punkt der Laufzeit gültig ist.
    Immer in der Annnahme das du Pointer nicht nur funktionslokal verwendest.

    Was ist an dieser einen zusätzlichen Zeile (p = 0) chaotisch ? Oder meinst du die
    Überprüfungen ?

    mfg JJ



  • John Doe schrieb:

    Wenn ich mehrfach n = 0 schreibe so zeugt das von Paranoia, stellt meines
    Erachtens aber keinen Fehler dar.

    wer n=0;n=0; schreibt, der hat ein ernsthaftes problem.
    was hat das mit paranoia zu tun? nach n=0; ist n 0. oder schreiben wir statt
    n=0; lieber gleich

    while(n!=0) n=0;
    

    dann koennen wir ganz sicher sein 😉

    Aber: in C++ zerstoeren wir unsere resourcen aber in einem dtor. wenn ein dtor nun '2x mal aufgerufen' wird, also sich 2 dtors eine arbeit teilen - dann _hast_ du ein problem. denn wie sonst, koennte man 2x delete aufrufen?

    Ich
    verstecke also keinen Fehler sondern vermeide ihn.

    Wilder Zeiger und NULL Zeiger sind 2 Komplett verschiedene Sachen...

    Ein NULL Zeiger ist ein valider Zeiger, der eben auf nichts zeigt.
    ein wilder zeiger (den du immer NULLst) ist ein programmierfehler.

    sobald er irgendwo auftritt, hast du einen logikfehler im programm. man kann ihn zwar verstecken, indem man einen NULL zeiger aus ihm mach, der Logikfehler bleibt aber erhalten.

    und nochmals:
    ich bin nicht generell gegen ein 0 setzen von zeigern - aber eben nur dann, wenn sie ein flag sind. aber wenn ich einen zeiger zerstoere, dann ist er tot. sobald ich ihn verwenden will, habe ich einen logikfehler im programm. ausnahmen sind natuerlich, wenn der zeiger selber ein flag ist und 0 heisst "ich zeige gerade auf garnichts".

    das problem ist, dass du einen illegalen (nicht vorkommenduerfenden) zustand (verwendung wilder zeiger) versteckst. dadurch kannst du dir fehler einfangen.

    einigen wir uns wenigstens darauf: dass es keinen mehrnutzen bringt, alle zeiger auf 0 zu setzen.



  • John Doe schrieb:

    Was ist an dieser einen zusätzlichen Zeile (p = 0;) chaotisch ? Oder meinst du die
    Überprüfungen ?

    nee, ich meinte die Tatsache, dass bei dir keiner weiß ob der Pointer gültig ist oder nicht.

    Das ist für mich Chaos.

    In C++ lässt sich die Lebenszeit von Objekten doch gut regulieren, dank Destruktoren.
    Ich meine, schon klar dass es in der Praxis vielleicht nicht immer so rosig aussieht, aber generell sollte man das zumindest versuchen und nicht auf gut glück die Zeiger auf Null setzen weil man keinen Plan mehr hat, was das Programm eigentlich so tut.


Anmelden zum Antworten