Letzte relevante Änderung: 15.04.2020

Code-Hölle

Das Internet wimmelt von Codeschnippseln für alle möglichen Anwendungszwecke. Darunter befinden sich sowohl brilliante Lösungen wie furchtbare Ideen, die vielleicht auf Anhieb funktioniert haben, aber absehbar zu großen Problemen führen werden. Selbst im Quellcode von ernsthaften Projekten finden sich zuweilen derartige Implementationen, wenn das Projekt aus den ersten Gehversuchen eines Programmierers stammt, oder dieser einfach ein Brett vor dem Kopf hatte. Dieser Artikel stellt eine kommentierte kleine Sammlung von derartigen schlechten Einfällen dar – gleichsam als Warnung und zur Unterhaltung – auf das künftig andere Fehler gemacht werden, die ich dann auch hier aufnehmen kann.

Inhaltsverzeichnis:

„Busy-Wait“

Sleep, Busy-Wait, C

Wenn man gerade keine Warte-Funktion in der Standardbibliothek zur Hand hat, wird immer wieder gerne auf Busy-Wait (dt.: geschäftiges Warten) zurückgegriffen, also eine Implementation, die die zu überbrückende Zeitspanne damit verbringt, die Rechenzeit zu verbrennen. Dass das keine ideale Lösung ist, muss ich wohl nicht näher erläutern, und seit C++11 std::this_thread::sleep_for() eingeführt hat, entfällt auch der letzte Grund dafür, eine solche Implementation zu verwenden: Plattformunabhängigkeit. Der Autor folgender Zeilen hat es jedoch bedauerlicherweise nicht geschafft, ein plattformunabhängiges Busy-Wait zu implementieren, denn die Einheit des Rückgabewerts von clock() ist platformabhängig und hätte mit CLOCKS_PER_SEC skaliert werden müssen...

void sleep(unsigned int milliseconds) {
    clock_t end = milliseconds + clock();
    while (end > clock())
        ;
}

Zufallszahlengenerator mit zufälliger Laufzeit

Zufallszahlen, C

„Wenn mir die Zufallszahl nicht passt, dann mach' ich mir halt eine Neue!“, dachte wohl der Autor folgender Funktion, die eine ganzzahlige Zufallszahl innerhalb eines bestimmten Wertebereichs liefern soll:

int clamped_rand(int bottom, int top) {
    int i = rand();
    while (i > top || i < bottom)
        i = rand();
    return i;
}

Solange also die Zufallszahl nicht im gewünschten Bereich liegt, wird einfach immer eine Neue erzeugt. Die Funktion liefert auch tatsächlich eine gleichverteilte Zufallszahl im gewünschten Bereich – wobei offen bleibt, wie lange sie dafür wohl braucht. Gewissermaßen ist an diesem Generator alles zufällig, denn die Laufzeit dieser Funktion ist vom (Pseudo-)Zufall abhängig, und je kleiner der Wertebereich, desto wahrscheinlicher ist, dass die Funktion eine lange Laufzeit hat. Mit einer gewissen Wahrscheinlichkeit kann die Funktion also auch mal einen Tag für die Ziehung brauchen, wenn die Sterne gerade schlecht stehen und stundenlang keine Zufallszahl im Zielbereich gezogen wird. Wonach der Programmierer eigentlich suchte – zumal es im konkreten Anwendungsfall keiner exakten Gleichverteilung bedurfte –, war folgendes (wobei es seit C++11 noch technisch bessere Lösungen aus <random> gibt, die dann auch wirklich gleichverteilt sind):

int clamped_rand(int bottom, int top) {
    return bottom + rand() % (top - bottom + 1);
}