(Un-)Sinn von Exceptions

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8474
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » So Jul 27, 2008 6:05 pm

Kerli hat geschrieben:
Xin hat geschrieben:
Kerli hat geschrieben: Durch die Exceptions brauche ich keine ausgefallene Steuerungslogik, es reichen nur ein paar deletes:
....
Und das ist alles...
...das will ich nicht hoffen, ansonsten fliegt Dir der Code im Fehlerfall um die Ohren.
Warum? Wenn eines der news fehlschlägt, wird der restliche Code nicht mehr ausgeführt, und nachher alles im Destruktur wieder gelöscht.
...den Satz lasse man sich auf der Zunge zergehen...
Kerli hat geschrieben:Soll ich wirklich alles posten? Das wären dann so ca. 4000 Zeilen Code...
Nein, der Konstruktor ist verantwortlich ein gültiges Objekt zu erzeugen. Was machen Deine Konstruktoren?
Ich gehe davon aus, dass Du es korrekt gelöst hast, der Aufbau weist darauf hin, sonst wäre es ein grober Schnitzer.

Aber es scheint Dir nicht so bewußt zu sein, dass Dein Aufbau mehr erfordert als nur try und catch.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Kerli » So Jul 27, 2008 6:17 pm

Xin hat geschrieben:
Kerli hat geschrieben:Soll ich wirklich alles posten? Das wären dann so ca. 4000 Zeilen Code...
Nein, der Konstruktor ist verantwortlich ein gültiges Objekt zu erzeugen. Was machen Deine Konstruktoren?
Ich gehe davon aus, dass Du es korrekt gelöst hast, der Aufbau weist darauf hin, sonst wäre es ein grober Schnitzer.

Aber es scheint Dir nicht so bewußt zu sein, dass Dein Aufbau mehr erfordert als nur try und catch.
Hier ist zb der Konstruktor vom GameHandler:

Code: Alles auswählen

GameHandler::GameHandler():
    save_game_        ( NULL ),
    load_             ( false),
    show_summary_     ( true ),
    bank_             ( NULL ),
    board_            ( NULL ),
    first_dice_       ( NULL ),
    second_dice_      ( NULL ),
    count_doubles_    ( 0    ),
    next_player_      ( false),
    quit_             ( false),
    msg_              ( "messages_en.xml" )
  {

  }
Aber ich glaube die anderen jetzt aufzulisten ist nicht mehr nötig. Ich finde wir sollten jetzt einmal zu einem Ende kommen. Ich könnte zwar auch noch die anderen Codeteile posten und dann könntest du teilweise Alternativen angeben, aber ich glaube es sollte einfach jeder für sich selbst entscheiden ob er jetzt etwas lieber mit einer Exception oder mit einem if löst.
Aber bei gewissen Fällen wird es sicher auch mit Exceptions schöner sein, währenddessen es woanders wieder völlig falsch sein kann.
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8474
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » So Jul 27, 2008 6:38 pm

Kerli hat geschrieben:
Xin hat geschrieben:
Kerli hat geschrieben:Soll ich wirklich alles posten? Das wären dann so ca. 4000 Zeilen Code...
Nein, der Konstruktor ist verantwortlich ein gültiges Objekt zu erzeugen. Was machen Deine Konstruktoren?
Ich gehe davon aus, dass Du es korrekt gelöst hast, der Aufbau weist darauf hin, sonst wäre es ein grober Schnitzer.

Aber es scheint Dir nicht so bewußt zu sein, dass Dein Aufbau mehr erfordert als nur try und catch.
Hier ist zb der Konstruktor vom GameHandler:
Der Konstruktor ist korrekt.
Wichtig ist hier folgendes: Du initialisiert Variablen mit NULL, nur um sie anschließend wieder überschreiben. Die Regel ist also aufwendiger, um Ausnahmen zu möglichen. Die Ausnahme wird im Idealfall nie ausgeführt, die Regel wird aber immer aufwendiger.

Bei delete musst Du berücksichtigen, dass delete - im Gegensatz zu free - erst überprüft, ob das Objekt ungleich NULL ist. Der delete-Aufruf auf ein Null-Objekt ist also nicht gefährlich, aber überflüssig. Überflüssige Deletes verbrauchen also Rechenleistung (ich weiß, der eine Takt... auch wenn's mehrere sind).

GameHandler klingt nach einem sehr abstrakten Layer - wenn überhaupt, haben Exceptions hier Sinn. Daher werden wir hier keinen diskussionswürdigen Streitpunkt finden.
Kerli hat geschrieben:...aber ich glaube es sollte einfach jeder für sich selbst entscheiden ob er jetzt etwas lieber mit einer Exception oder mit einem if löst.
Aber bei gewissen Fällen wird es sicher auch mit Exceptions schöner sein, währenddessen es woanders wieder völlig falsch sein kann.
So sieht es aus.

Wichtig ist mir letztendlich, dass die meisten Entwickler, die bei Exceptions begeistert jubeln, oftmals nicht wissen, was sie dafür bezahlen. Goto ist verschrieen, weil man sich damit quer durch den ganzen Code bewegt, bei throw ist es ebenso, man hat die gleichen Risiken (abgesehen davon, dass manche(!) Variablen über den Destruktor zerstört werden). Springt man mit throw quer durch das Programm wird das auf einmal als moderne Programmierung verkauft. Und nicht zu vergessen, ein throw ist ein Goto nach irgendwo, denn man weiß nicht, wo man letztendlich gefangen wird und wie fähig das jeweilige catch ist.

Verschachtelte ifs oder Wächter sind bewährte, leicht zu dokumentierende Codeaufbauten, die den Vorteil haben, dass man an jedem Punkt exakt sagen kann, in welchem Zustand sich der Algorithmus befindet und nebenher auch noch schneller als Exceptions abläuft. Vorteile, die man nicht zu schnell aufgeben sollte. Exceptions sind eine alternative Fehlerbehandlung, aber zu häufig wird es die einzige.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Kerli » So Jul 27, 2008 8:55 pm

Xin hat geschrieben:
Kerli hat geschrieben: Hier ist zb der Konstruktor vom GameHandler:
Der Konstruktor ist korrekt.
Wichtig ist hier folgendes: Du initialisiert Variablen mit NULL, nur um sie anschließend wieder überschreiben. Die Regel ist also aufwendiger, um Ausnahmen zu möglichen. Die Ausnahme wird im Idealfall nie ausgeführt, die Regel wird aber immer aufwendiger.
Aber da ich das ganze in der Initialisierungsliste mache, sollte das kaum zusätzliche Zeit brauchen.
Xin hat geschrieben: Bei delete musst Du berücksichtigen, dass delete - im Gegensatz zu free - erst überprüft, ob das Objekt ungleich NULL ist. Der delete-Aufruf auf ein Null-Objekt ist also nicht gefährlich, aber überflüssig. Überflüssige Deletes verbrauchen also Rechenleistung (ich weiß, der eine Takt... auch wenn's mehrere sind).
Schon aufgrund der Typsicherheit sollte man in C++ wohl eher new/delete als malloc/free verwenden, aber auch hier macht das nicht viel aus, da das Erstellen und Löschen der Objekte nur einmal erfolgt und nicht in einer Schleife, wo man Optimierungen viel deutlicher merken wird.
Xin hat geschrieben: GameHandler klingt nach einem sehr abstrakten Layer - wenn überhaupt, haben Exceptions hier Sinn. Daher werden wir hier keinen diskussionswürdigen Streitpunkt finden.
Ja es ist recht gut durchgeplant - wir haben auch ein 15 seitiges Designdokument verfasst ;) - und es basiert auch auf einer komplexen Klassenhierarchie von der das Klassendiagramm nicht einmal lesbar auf eine A4 Seite gepasst hat. Auch wenn das nicht guten Code garantiert so erleichtert es das zumindest auf jeden Fall...
Xin hat geschrieben:
Kerli hat geschrieben:...aber ich glaube es sollte einfach jeder für sich selbst entscheiden ob er jetzt etwas lieber mit einer Exception oder mit einem if löst.
Aber bei gewissen Fällen wird es sicher auch mit Exceptions schöner sein, währenddessen es woanders wieder völlig falsch sein kann.
So sieht es aus.

Wichtig ist mir letztendlich, dass die meisten Entwickler, die bei Exceptions begeistert jubeln, oftmals nicht wissen, was sie dafür bezahlen.

[...]

Verschachtelte ifs oder Wächter sind bewährte, leicht zu dokumentierende Codeaufbauten, die den Vorteil haben, dass man an jedem Punkt exakt sagen kann, in welchem Zustand sich der Algorithmus befindet und nebenher auch noch schneller als Exceptions abläuft. Vorteile, die man nicht zu schnell aufgeben sollte. Exceptions sind eine alternative Fehlerbehandlung, aber zu häufig wird es die einzige.
Ich hab ja auch nie behauptet, dass man nur Exceptions verwenden sollte. Ich hab nur ausdrücken wollen, dass sie manchmal eine gute Alternative zur klassischen Fehlerbehandlung darstellen.
Auch ich verwende Wächter und verschachtelte ifs, aber wenn es mir sinnvoll erscheint verwende ich genauso auch einmal Exceptions.
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8474
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » So Jul 27, 2008 9:12 pm

Kerli hat geschrieben:Aber da ich das ganze in der Initialisierungsliste mache, sollte das kaum zusätzliche Zeit brauchen.
Egal, wie Du 'die paar Takte' in andere Worte packst, Du verschwendest Zeit.
Kerli hat geschrieben:
Xin hat geschrieben: GameHandler klingt nach einem sehr abstrakten Layer - wenn überhaupt, haben Exceptions hier Sinn. Daher werden wir hier keinen diskussionswürdigen Streitpunkt finden.
Ja es ist recht gut durchgeplant - wir haben auch ein 15 seitiges Designdokument verfasst ;) - und es basiert auch auf einer komplexen Klassenhierarchie von der das Klassendiagramm nicht einmal lesbar auf eine A4 Seite gepasst hat. Auch wenn das nicht guten Code garantiert so erleichtert es das zumindest auf jeden Fall...
Was hast Du in der Regel? Kein Designdokument, eine hochkomplexe Klassenhierarchie und keine Dokumentation, weiterhin den Druck, Features zu produzieren.

Das Klassendiagram meines Compilers habe ich mal so zurecht geschoben, dass ich es auf eine Wand tapezieren kann. Nicht, dass ich es gemacht hätte, aber 'nicht lesbar auf einer DIN A4-Seite', ist sehr überschaubar. Eine Exception, die in meinem Compiler von einer Ecke des Zimmers in die nächste Ecke springt, überfordert mich. Wenn ich überfordert bin, mache ich Fehler, für die ich mehr Aufwand im Bereich der Fehlerbehandlung benötige.
Kerli hat geschrieben:Ich hab ja auch nie behauptet, dass man nur Exceptions verwenden sollte. Ich hab nur ausdrücken wollen, dass sie manchmal eine gute Alternative zur klassischen Fehlerbehandlung darstellen.
Auch ich verwende Wächter und verschachtelte ifs, aber wenn es mir sinnvoll erscheint verwende ich genauso auch einmal Exceptions.
Verwende eine Exception, die nur einen Zweck hat: Zu retten, was zu retten ist und das Programm danach abkacken lässt. Alles andere, regel auf altmodische Art.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von fat-lobyte » Mo Jul 28, 2008 10:09 am

Du sagst, es gibt keine Beispiele, die die Verwendung von Exceptions rechtfertigen würden. Sieh dir diesen Code an, und sag mir dass das hier etwas anderes ist als "throw NameDerFirmaException(errstr)".

Es ist aus der Datei "malloc.c", aus der glibc 2.7, die so ziemlich jeder mit aktuellem GNU/Linux system verwendet:

Code: Alles auswählen

_int_free(mstate av, Void_t* mem)
{
  mchunkptr       p;           /* chunk corresponding to mem */
  INTERNAL_SIZE_T size;        /* its size */
  mfastbinptr*    fb;          /* associated fastbin */
  mchunkptr       nextchunk;   /* next contiguous chunk */
  INTERNAL_SIZE_T nextsize;    /* its size */
  int             nextinuse;   /* true if nextchunk is used */
  INTERNAL_SIZE_T prevsize;    /* size of previous contiguous chunk */
  mchunkptr       bck;         /* misc temp for linking */
  mchunkptr       fwd;         /* misc temp for linking */

  const char *errstr = NULL;

  p = mem2chunk(mem);
  size = chunksize(p);

  if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
      || __builtin_expect (misaligned_chunk (p), 0))
    {
      errstr = "free(): invalid pointer";
    errout:
      malloc_printerr (check_action, errstr, mem);
      return;
    }
  /* We know that each chunk is at least MINSIZE bytes in size.  */
  if (__builtin_expect (size < MINSIZE, 0))
    {
      errstr = "free(): invalid size";
      goto errout;
    }

  check_inuse_chunk(av, p);

  if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())

#if TRIM_FASTBINS
      /*
        If TRIM_FASTBINS set, don't place chunks
        bordering top into fastbins
      */
      && (chunk_at_offset(p, size) != av->top)
#endif
      ) {

    if (__builtin_expect (chunk_at_offset (p, size)->size <= 2 * SIZE_SZ, 0)
        || __builtin_expect (chunksize (chunk_at_offset (p, size))
                             >= av->system_mem, 0))
      {
        errstr = "free(): invalid next size (fast)";
        goto errout;
      }

    set_fastchunks(av);
    fb = &(av->fastbins[fastbin_index(size)]);
    /* Another simple check: make sure the top of the bin is not the
       record we are going to add (i.e., double free).  */
    if (__builtin_expect (*fb == p, 0))
      {
        errstr = "double free or corruption (fasttop)";
        goto errout;
      }

    if (__builtin_expect (perturb_byte, 0))
      free_perturb (mem, size - SIZE_SZ);

    p->fd = *fb;
    *fb = p;
  }


  else if (!chunk_is_mmapped(p)) {
    nextchunk = chunk_at_offset(p, size);

    /* Lightweight tests: check whether the block is already the
       top block.  */
    if (__builtin_expect (p == av->top, 0))
      {
        errstr = "double free or corruption (top)";
        goto errout;
      }
    /* Or whether the next chunk is beyond the boundaries of the arena.  */
    if (__builtin_expect (contiguous (av)
                          && (char *) nextchunk
                          >= ((char *) av->top + chunksize(av->top)), 0))
      {
        errstr = "double free or corruption (out)";
        goto errout;
      }
    /* Or whether the block is actually not marked used.  */
    if (__builtin_expect (!prev_inuse(nextchunk), 0))
      {
        errstr = "double free or corruption (!prev)";
        goto errout;
      }

    nextsize = chunksize(nextchunk);
    if (__builtin_expect (nextchunk->size <= 2 * SIZE_SZ, 0)
        || __builtin_expect (nextsize >= av->system_mem, 0))
      {
        errstr = "free(): invalid next size (normal)";
        goto errout;
      }

    if (__builtin_expect (perturb_byte, 0))
      free_perturb (mem, size - SIZE_SZ);

    /* consolidate backward */
    if (!prev_inuse(p)) {
      prevsize = p->prev_size;
      size += prevsize;
      p = chunk_at_offset(p, -((long) prevsize));
      unlink(p, bck, fwd);
    }

    if (nextchunk != av->top) {
      /* get and clear inuse bit */
      nextinuse = inuse_bit_at_offset(nextchunk, nextsize);

      /* consolidate forward */
      if (!nextinuse) {
        unlink(nextchunk, bck, fwd);
        size += nextsize;
      } else
        clear_inuse_bit_at_offset(nextchunk, 0);

      bck = unsorted_chunks(av);
      fwd = bck->fd;
      p->fd = fwd;
      p->bk = bck;
      if (!in_smallbin_range(size))
        {
          p->fd_nextsize = NULL;
          p->bk_nextsize = NULL;
        }
      bck->fd = p;
      fwd->bk = p;

      set_head(p, size | PREV_INUSE);
      set_foot(p, size);

      check_free_chunk(av, p);
    }

    else {
      size += nextsize;
      set_head(p, size | PREV_INUSE);
      av->top = p;
      check_chunk(av, p);
    }


    if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
      if (have_fastchunks(av))
        malloc_consolidate(av);

      if (av == &main_arena) {
#ifndef MORECORE_CANNOT_TRIM
        if ((unsigned long)(chunksize(av->top)) >=
            (unsigned long)(mp_.trim_threshold))
          sYSTRIm(mp_.top_pad, av);
#endif
      } else {
        /* Always try heap_trim(), even if the top chunk is not
           large, because the corresponding heap might go away.  */
        heap_info *heap = heap_for_ptr(top(av));

        assert(heap->ar_ptr == av);
        heap_trim(heap, mp_.top_pad);
      }
    }
  }
  else {
#if HAVE_MMAP
    munmap_chunk (p);
#endif
  }
}
Es ist C- code, also keine Exceptions. Ich habe die 'errstr = "double free or corruption"; goto errout;' nicht gezählt, aber ich denke es ist klar dass genug drinnen sind.
Was findest du besser in diesem Fall? Exceptions zu verwenden? Oder goto ?
Oder würdest du vielleicht lieber das ganze komplett umschreiben, und "den status des algorithmus zu jederzeit wissen", und angemessen auf Fehler reagieren? Ich bin mir sicher, die glibc- Entwickler freuen sich auf deine Patches.
Das hier ist Real- World Code. Code der auch von Kritischen Anwendungen verwendet wird. Und ich bin mir ziemlich sicher, dass sehr viele Anwendungen (und Bibliotheken), die in C geschrieben sind den gleichen Mechanismus verwenden.
Ich sags dir ganz ehrlich, anstatt solche goto's zu schreiben werfe ich lieber eine exception, die im übergeordneten frame aufgeräumt wird.
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8474
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » Mo Jul 28, 2008 11:48 am

fat-lobyte hat geschrieben:Du sagst, es gibt keine Beispiele, die die Verwendung von Exceptions rechtfertigen würden.
Auch hier werde ich jetzt Klartext sprechen, auch wenn das vielleicht unhöflich klingt.
Es macht überhaupt keinen Spaß, zu diskutieren, wenn ich genauso gut mit einer Wand reden könnte. Ich kann verstehen, dass schwer greifbare Dinge unverstanden bleiben, wie die Schwierigkeiten, Exceptions am richtigen Punkt abzufangen, dafür muss man sich mal eben ein komplexes Beispiel-Programm aufbauen, was die meisten hier vermutlich nie geschrieben haben.

Ich kann wohl nicht davon ausgehen, dass meine Argumentation nachvollzogen wird, wenn selbst greifbare Dinge wie:
Xin hat geschrieben:Nochmals: Ich bin nicht gegen Exceptions, aber ich bin absolut gegen die Verwendung von Exceptions als Regel. Dass Dateien nicht gefunden werden ist keine Ausnahme.
oder
Xin hat geschrieben:Ich kann gute Beispiele für Exceptions konstruieren, aber ich habe noch nie jemanden gesehen, der ein gutes Beispiel konstruierte und gleichzeitig für Exceptions war. Wer gute Beispiele konstruiert, weiß, dass sie Exceptions dafür nicht verwendet werden.
Ein Programm, dass über mehr als 5 Ausnahmen verfügt missbraucht Exceptions. Und eigentlich denke ich, dass 2 schon über die obere Grenze hinausgeht.
Jetzt kommt von Dir der Spruch 'Du sagst, es gibt keine Beispiele, die die Verwendung von Exceptions rechtfertigen würden.', ich soll also gegen Dinge argumentieren, die überhaupt nicht Teil meiner Argumentation sind. Du schiebst mir hier Sachen unter, gegen die Du dann argumentierst? Wenn auf meine Argumentation nicht eingegangen wird, brauche ich sie auch nicht aufzuschreiben.
fat-lobyte hat geschrieben:Sieh dir diesen Code an, und sag mir dass das hier etwas anderes ist als "throw NameDerFirmaException(errstr)".

Es ist aus der Datei "malloc.c", aus der glibc 2.7, die so ziemlich jeder mit aktuellem GNU/Linux system verwendet:

...

Es ist C- code, also keine Exceptions. Ich habe die 'errstr = "double free or corruption"; goto errout;' nicht gezählt, aber ich denke es ist klar dass genug drinnen sind.
Was findest du besser in diesem Fall? Exceptions zu verwenden? Oder goto ?
Goto finde ich hier angebracht, die Position des Labels empfinde ich hier als schlecht.

Das ist eine absolute Low-Level-Funktion und das bedeutet, dass es absolut egal ist, wie die Funktion aussieht, hier ist die erste Priorität Geschindigkeit um absolut jeden Preis. Es muss garantiert funktionieren, aber es ist absolut legitim, dass man sich in so eine Funktion einen ganzen Tag einarbeiten muss, wenn sie dafür ein paar Takte Rechenzeit spart.

Zwei Dinge:
1) Du bringst mir hier einen Code, der ein Goto enthält, weil ich throw mit Goto vergleiche. Ich vergleiche Throw nicht mit einem Goto, das sich innerhalb einer Funktion bewegt, also überschaubar ist, sondern dass quer durch den Code springt. Bitte lies, was ich schreibe und wenn Du es nicht verstehst, dann frag nach. Aber Du interpretierst hier unreflektiert Dinge hinein, die ich so nicht beschrieben habe.
Xin hat geschrieben:Und nicht zu vergessen, ein throw ist ein Goto nach irgendwo, denn man weiß nicht, wo man letztendlich gefangen wird und wie fähig das jeweilige catch ist.
Dieser Code enthält ein lokales Goto, sehr leicht nachzuvollziehen. throw springt über Dateien und Namensräume hinweg zu einem Ziel, dass ich bei throw nichtmals kenne.
Das kann Goto auch, darum ist es (zu Recht) verschrieen. Ein goto innerhalb einer Funktion ist aber diskutabel. Nach Möglichkeit ist es zu vermeiden und die Möglichkeit ist fast immer gegeben. Aber man kann dadrüber diskutieren.

2) Wollt ihr mir jetzt laufend Codes vorwerfen, bis ihr das Beispiel gefunden habt, bei dem ich Exceptions als gute Möglichkeit ansehe und mir anschließend mit einem Spruch wie 'Du sagst, es gibt keine Beispiele, die die Verwendung von Exceptions rechtfertigen würden.' zu erklären, dass ich ja grade meine Überzeugung widerlegt habe?
fat-lobyte hat geschrieben:Oder würdest du vielleicht lieber das ganze komplett umschreiben, und "den status des algorithmus zu jederzeit wissen", und angemessen auf Fehler reagieren? Ich bin mir sicher, die glibc- Entwickler freuen sich auf deine Patches.
Ich würde das goto tatsächlich rausnehmen und

Code: Alles auswählen

      errstr = "free(): invalid pointer";
      malloc_printerr (check_action, errstr, mem);
      return;
als Macro anpassen. Das würde die Funktion geringfügig beschleunigen, aber auch geringfügig vergrößern. malloc stammt noch aus einer Zeit, in der Kernel möglichst klein sein sollte, damit er auf Maschinen lief, die soviel Speicher haben, wie der Kernel heute Speicher verbraucht.
fat-lobyte hat geschrieben:Ich sags dir ganz ehrlich, anstatt solche goto's zu schreiben werfe ich lieber eine exception, die im übergeordneten frame aufgeräumt wird.
Dieses Goto hat nichts mit mit einem throw zu tun.
Das Goto ist in der Funktion unangebracht und problemlos zu entfernen.

Eine Exception ist in der Funktion absolut unangebracht, wie Exceptions grundsätzlich in Low-Level-Funktionen unangebracht sind.
Ich gehe noch einen Schritt weiter: In Lowlevel Funktionen ist jegliche Fehlerbehandlung unangebracht, beispiel sqrt. Bereichne ich sqrt( -1 ), dann habe ich kein Problem damit, wenn ich ein falsches Ergebnis bekomme. Das ist nicht der Fehler von sqrt(), sondern der Fehler des Programmierers, der sqrt aufruft. Low-Level-Funktionen haben eine Aufgabe in einem wohldefinierten Parameterbereich und die Aufgabe haben sie so schnell wie nur irgendmöglich erledigen.
Asserts helfen dem Entwickler während der Entwicklung dafür zu sorgen, dass der Programmierer sich ausschließlich in dem Bereich bewegt, aber als Produktivsystem, will ich hier Dampf sehen und keine Funktionen, die mit angezogener Handbremse unterwegs sind.

Wer Programmiert, sollte wissen, was er tut und in welchem Bereich er sich bewegt. Wer als Entwickler an die Hand genommen werden muss, darf sich nur in Bereichen bewegen, wo die Lib ihn an die Hand nimmt. Willkommen bei Java und .NET, aber so ein Programmierer möge sich bitte nicht in C++ bewegen.

Wer Programmiert, sollte wissen, was er tut und in welchem Bereich er sich bewegt. Wer als Entwickler an die Hand genommen werden muss, darf sich nur in Bereichen bewegen, wo die Lib ihn an die Hand nimmt. Willkommen bei Java und .NET, aber so ein Programmierer möge sich bitte nicht in C++ bewegen.
Wer Mathematik betreibt, sollte verstehen, dass Computer-Mathematik nicht der Schul-Mathematik entspricht. Wenn er dann die Schulmathematik nicht beherrscht und nicht weiß, dass die Wurzel aus negativen Zahlen eine komplexer Wert wird, also double sqrt( double ) für negative Werte nicht gehen kann... ich bin dafür, dass eine Sprache den Entwickler maximal unterstützt, aber ich setze an den Entwickler Grundvoraussetzungen. sqrt(), wie auch malloc() sollten ein assert enthalten, dass die Erwartung ausdrückt, dass eine positve Zahl verlangt wird. Ansonsten erwarte ich, dass ein Entwickler seine Algorithmen so formuliert, dass ein assert niemals anspricht.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten