Wieviel Kontrolle ist empfohlen



  • volkard schrieb:

    Christoph schrieb:

    Außerdem ist es immer noch genausowenig threadsicher, wenn der Vektor zwischen Zeile 3 und 4 wächst.

    (s/wächst/schrumpft/)

    Nein, ich meinte "wächst". Dann liest Zeile 3 nämlich noch Müll (wegen dem ungültigen Index), das if in Zeile 5 geht aber davon aus, dass der Index im Range liegt.



  • Gut, mein letzter Beitrag war ein Griff ins Klo, gebe ich zu. Ohne entsprechende Synchronisierungsmöglichkeiten (locken war ja nicht "erlaubt") gehts halt doch nicht.

    volkard schrieb:

    T operator[int i] {
        if (i >= size) { 
            throw new IndexException(i); 
        } 
    
        return data[i];
    }
    

    Verlagert das Problem lediglich zwischen Zeile 4 und 6, nachdem nach der Überprüfung etwas entfernt werden könnte.

    Ich wollte aber eigentlich mit dem Argument de thread-sicheren Datenstrukturen darauf hinaus, dass man sich diese "verbaut", wenn man eine Zugriffsmöglichkeit ohne Exceptions (Stichwort: throw()) anbietet. Für die paar Fälle in denen man den Index-Bereich "weiß" zahlt sich eine zusätzliche Zugriffsmöglichkeit nicht aus. Es besteht bei 2 Methoden aber trotzdem die Gefahr, dass Fehler verschluckt werden.



  • exceptions` schrieb:

    Ich wollte aber eigentlich mit dem Argument de thread-sicheren Datenstrukturen darauf hinaus, dass man sich diese "verbaut", wenn man eine Zugriffsmöglichkeit ohne Exceptions (Stichwort: throw()) anbietet.

    erklär das mal auf russisch. so versteh ichs nicht.
    außerdem widerspreche ich mal prophylaktisch.



  • exceptions` schrieb:

    Ich wollte aber eigentlich mit dem Argument de thread-sicheren Datenstrukturen darauf hinaus, dass man sich diese "verbaut", wenn man eine Zugriffsmöglichkeit ohne Exceptions (Stichwort: throw()) anbietet. Für die paar Fälle in denen man den Index-Bereich "weiß" zahlt sich eine zusätzliche Zugriffsmöglichkeit nicht aus.

    Also bitte. Was heißt denn für dich "die paar Fälle"? Single-Threaded Programme? Daten auf die ausschließlich innerhalb eines Worker-Threads zugegriffen wird?

    Und was heißt denn "zahlt sich eine zusätzliche Zugriffsmöglichkeit nicht aus"?

    T at( index )
    {
      check index
      return op[]( index )
    }
    


  • volkard schrieb:

    exceptions` schrieb:

    Ich wollte aber eigentlich mit dem Argument de thread-sicheren Datenstrukturen darauf hinaus, dass man sich diese "verbaut", wenn man eine Zugriffsmöglichkeit ohne Exceptions (Stichwort: throw()) anbietet.

    erklär das mal auf russisch. so versteh ichs nicht.
    außerdem widerspreche ich mal prophylaktisch.

    Gut, nehmen wir an, wir haben es nun STL-like implementiert und wollen im Zuge einer Multi-Threading Anwendung dem operator[] einen Index-Range Check geben. Was machst du, wenn der Index ungültig ist?

    Und was heißt denn "zahlt sich eine zusätzliche Zugriffsmöglichkeit nicht aus"?

    Ich überschwemme meine öffentliche Schnittstelle ungern mit redundanten Methoden. Beide erledigen im Prinzip die selbe Aufgabe, nur eine etwas restriktiver. Warum sollte man sich also nicht einfach im Zuge einer einfachen Schnittstelle nicht auf den gemeinsamen Nenner (die restriktivere Variante) entscheiden?



  • exceptions` schrieb:

    Gut, nehmen wir an, wir haben es nun STL-like implementiert und wollen im Zuge einer Multi-Threading Anwendung dem operator[] einen Index-Range Check geben. Was machst du, wenn der Index ungültig ist?

    irrige annahme.
    der op[] hat kein range-checking (außer mit assert) verdient.
    eine at-funktion würde exceptions werfen. auch im multithreading-fall.



  • volkard schrieb:

    irrige annahme.
    der op[] hat kein range-checking (außer mit assert) verdient.
    eine at-funktion würde exceptions werfen. auch im multithreading-fall.

    Was machst du dann, wenn der Index ungültig ist, UDB? Und sag mir jetzt nicht, dass du im Debug-Mode eh ein assert hast, denn wie ich bereits gesagt habe, heißt Release-Mode ja nicht per Definition, dass keine Fehler mehr auftreten können. Das klingt für mich irgendwie danach als würdest du die Fehler "verschlucken" ...



  • exceptions` schrieb:

    Was machst du dann, wenn der Index ungültig ist, UDB?

    jup.

    Und sag mir jetzt nicht, dass du im Debug-Mode eh ein assert hast, denn wie ich bereits gesagt habe, heißt Release-Mode ja nicht per Definition, dass keine Fehler mehr auftreten können. Das klingt für mich irgendwie danach als würdest du die Fehler "verschlucken" ...

    ich mach halt die programmierfehler weg.



  • volkard schrieb:

    Und sag mir jetzt nicht, dass du im Debug-Mode eh ein assert hast, denn wie ich bereits gesagt habe, heißt Release-Mode ja nicht per Definition, dass keine Fehler mehr auftreten können. Das klingt für mich irgendwie danach als würdest du die Fehler "verschlucken" ...

    ich mach halt die programmierfehler weg.

    Ich auch, allerdings muss ich bei Exceptions beinahe blind sein, um sie zu übersehen.



  • Ich überschwemme meine öffentliche Schnittstelle ungern mit redundanten Methoden. Beide erledigen im Prinzip die selbe Aufgabe, nur eine etwas restriktiver. Warum sollte man sich also nicht einfach im Zuge einer einfachen Schnittstelle nicht auf den gemeinsamen Nenner (die restriktivere Variante) entscheiden?

    Dafür wurder Vererbung erfunden. Die Basisklasse ist thread-unsafe, eine Unterklasse ist thread-save.
    Oder man hat halt 2 Vectors, einer ist Thread-unsafe, der andere -safe. Dann noch ein Kopier-Kontruktor für die beiden und alles ist wunderbar 🙂

    PS: Juhu 800 Beiträge 🕶



  • exceptions` schrieb:

    Ich überschwemme meine öffentliche Schnittstelle ungern mit redundanten Methoden. Beide erledigen im Prinzip die selbe Aufgabe, nur eine etwas restriktiver. Warum sollte man sich also nicht einfach im Zuge einer einfachen Schnittstelle nicht auf den gemeinsamen Nenner (die restriktivere Variante) entscheiden?

    Ach ja. Hälst du z.B. std::find auch für redundant? Macht ja im Prinzip das gleiche wie std::find_if... oder std::stable_sort? Nein, halt, der "gemeinsame Nenner" wäre ja std::stable_sort, also sollte man wohl std::sort rausschmeißen, was?



  • DEvent schrieb:

    Dafür wurder Vererbung erfunden. Die Basisklasse ist thread-unsafe, eine Unterklasse ist thread-save.
    Oder man hat halt 2 Vectors, einer ist Thread-unsafe, der andere -safe. Dann noch ein Kopier-Kontruktor für die beiden und alles ist wunderbar.

    Dafür hat man wenn schon Schnittstellen zu verwenden und keine Vererbung (oder willst du behaupten eine thread-sichere Datenstruktur ist eine thread-unsichere Datenstruktur - IS-A Principle), geht aber sowieso völlig am Thema vorbei. Threads wurden lediglich deswegen in die Diskussion miteingebunden gebracht um am Argument "man muss nicht immer den Index prüfen" zu rütteln.

    Ach ja. Hälst du z.B. std::find auch für redundant? Macht ja im Prinzip das gleiche wie std::find_if... oder std::stable_sort? Nein, halt, der "gemeinsame Nenner" wäre ja std::stable_sort, also sollte man wohl std::sort rausschmeißen, was?

    Also der Vergleich ist ja jetzt schon etwas weit hergeholt und das weißt du auch selbst ..

    Ich denke aber langsam lässt die Wirkung der Drogen nach und ich sehe ein, dass ein Range-Check inkl. Exception untragbar viel Performance verbrauchen würde. In diesem Falle ist es natürlich absolut gerechtfertigt sich nicht gegen "undefined behaviour" abzusichern.



  • exceptions` schrieb:

    Threads wurden lediglich deswegen in die Diskussion miteingebunden gebracht um am Argument "man muss nicht immer den Index prüfen" zu rütteln.

    ein argument, das ich nicht verstehe. wer um alles in der welt plant denn ernsthaft so ein programm, das zufällig oft funktioniert aber garantiert nicht immer funktioniert, und führt diesen wirklich schlechten stil (nichtsynchronisierte interthreadkommunikation) dann als argument auf, um einen anderen schlechten stil (exceptions gegen programmierfehler) zu verteidigen? womit habe ich das verdient?



  • Nachdem du es anscheinend nich verstehen willst, frage ich dich, welchen Vorteil besitzt eine zusätzliche Zugriffsmöglichkeit, die keine Exceptions wirft? Komm mir jetzt aber nicht mit fadenscheinigen Argumenten wie Performance, ...

    volkard schrieb:

    schlechten stil (exceptions gegen programmierfehler)

    Natürlich ist es schlechter Stil, wenn man sich undefined behaviour und stundenlanges Debuggen ersparen will, weil man den Fehler nicht findet. Es muss ja schlechter Stil sein, denn es erinnert zu stark an Java. 🙄



  • Aiaiai, was habe ich hier nur angerichtet 😉

    An sowas wie Multithreating hatte ich noch gar nicht gedacht.
    Mir ging es im Endeffekt nur darum, ob man wirklich alles kontrollieren muss
    oder manchmal auch einfach davon ausgehen kann ob etwas funktioniert(und auf die
    Intelligenz des Programmierers vertraut)

    Meine Idee war nur, wenn ich so eine Indexüberprüfung nicht einbaue, dann geht das
    wenn es hochkommt vlt jedes 10000000 mal daneben, aber dieses eine Mal kann ich ja verhinden, und eine if abfrage ist ja nicht wirklich teuer(in Assembler glaube ich einen cmp Befehl und danach ein Register auslesen, das dürften nur 4 Takte sein)

    Ich bin halt gerne auf der sicheren Seite 🙂



  • Wenn er einen Sprung in die andere Richtung erwartet hat, dann wird er auch noch die Pipeline entrümpeln mussen.



  • exceptions` schrieb:

    Komm mir jetzt aber nicht mit fadenscheinigen Argumenten wie Performance, ...

    doch. viel schlimmer noch, die auch beim kunden exceptionswerfende hat keinerlei vorteile.

    exceptions` schrieb:

    Natürlich ist es schlechter Stil, wenn man sich undefined behaviour und stundenlanges Debuggen ersparen will, weil man den Fehler nicht findet.

    im debug-mode ist doch assert an (bessergesagt ein aufgepimptes ASSERT). wegen indexgrenzenüberschreitungen gibr es kein stundenlanges debuggen. das war mal, als man noch wie in C programmiert hat. die indexgrenzenfehlersuche der letzten jahre hat mich zusammen vielleicht ne stunde gekostet und liegt nur dran, daß ich netterweise fremde programme durchgesehen hab.
    das ist so ein phänomen, wie das mit den speicherlöchern, die in modernem C++ so rar sind, wie naturblonde chinesen in bielefeld. sie sind sicher kein argument, nen garbage collector zu bauen. und das wird auch nicht dadurch geändert, daß anfänger die ersten jahre probleme damit haben.

    exceptions` schrieb:

    Es muss ja schlechter Stil sein, denn es erinnert zu stark an Java.

    es ist schlechter stil, weil es zu nicht wegzudiskutierenden kosten ein nicht-problem "repariert". ich will dich mal sehen, wenn du wegen eines programmierfehlers (und dazu gehört deine nichtsynchronisierte komnmunikation) die exception zweimal fliegen läßt, einmal "normal" und einmal aus einem destruktor im stack-unwinding heraus. machste assert an, siehste nur die erste. die ist nicht kritisch. machste assert aus, terminiert das programm, statt die exception in der main zu fangen. und da du das phänomen nicht kennst, gehen erstmal zwei arbeitstage drauf, das zu finden. vermutlich viel mehr, weil du ja mit deinem programmierfehler sporadische exceptions erzeugst.
    ein einfaches sofortiges und konsequentes asserten im debug-mode ist da die bessere taktik, glaub mir da einfach.



  • Mir ging es im Endeffekt nur darum, ob man wirklich alles kontrollieren muss
    oder manchmal auch einfach davon ausgehen kann ob etwas funktioniert(und auf die
    Intelligenz des Programmierers vertraut)

    Ich betrachte das eher von der anderen Seite und halte es nicht für eine großartige Darstellung der eigenen Intelligenz wenn man Klassen entwickelt, die unter Umständen undefined behaviour verursachen. Komischerweise wird es anscheinend bei Collections/Container geduldet, was ich einfach für ein Unding halte.

    im debug-mode ist doch assert an (bessergesagt ein aufgepimptes ASSERT). wegen indexgrenzenüberschreitungen gibr es kein stundenlanges debuggen. das war mal, als man noch wie in C programmiert hat. die indexgrenzenfehlersuche der letzten jahre hat mich zusammen vielleicht ne stunde gekostet und liegt nur dran, daß ich netterweise fremde programme durchgesehen hab.

    Das Problem dabei ist aber, dass erstmal der Fehler reproduziert werden muss ohne jegliche Informationen ausser den Angaben vom Kunden und die werden mehr als dürftig sein. Daraus ergibt sich auch gleich der Vorteil der "beim-Kunden-exceptionwerfenden-Version" durch z.B: zusätzliche Log-Datein, die er beim Bug Report angeben kann (selbst ohne Stack Trace gibt es einen Anhaltspunkt).

    und einmal aus einem destruktor im stack-unwinding

    Man merkt, dass dir die Argumente ausgehen, wenn du davon ausgehst, dass ich im Destruktor Exceptions werfe.



  • exceptions` schrieb:

    Es muss ja schlechter Stil sein, denn es erinnert zu stark an Java.

    Java kennt genauso Assertions wie c++.



  • exceptions` schrieb:

    und einmal aus einem destruktor im stack-unwinding

    Man merkt, dass dir die Argumente ausgehen, wenn du davon ausgehst, dass ich im Destruktor Exceptions werfe.

    wenn du nicht im destruktor datenbanken schließt, socket-partnern bescheidsagst, file-lockings entfernst, temp-dateien löscht und so fort, dann haste was ganz entscheidendes nicht verstanden. und natürlich können die dafür notwendigen daten in einem deiner kaputten arrays liegen.


Anmelden zum Antworten