Archiv

Posts Tagged ‘programmiersprachen’

Genau deswegen hasse ich C/C++

2010-08-21 16 Kommentare

Hier mal ein schönes Beispiel, warum ich C und C++ hasse. Nehmen wir doch dieses schöne, einfache Programm:

#include <stdio.h>

int main() {
	int zahl = 23;
	if (zahl > 5) {
		printf("Das sollte reichen: " + zahl);
	} else {
		printf("Das reicht nicht: " + zahl);
	}
}

Was gibt dieses Programm aus, wenn man es startet?

(Runterscrollen für die Lösung)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

Die Antwort lautet:

s reicht nicht: 

Also der Text aus dem else-Zweig, der eigentlich nicht aufgerufen werden kann, und auch noch am Anfang abgeschnitten, und die Zahl fehlt. Was ist passiert? Nun, die Zeichenketten werden hintereinander im Speicher abgelegt. Es wird sehr wohl der erste Zweig ausgeführt – aber es wird die Speicheradresse der ersten Zeichenkette genommen, die Zahl dazuaddiert und die Zeichenkette an dieser neuen Adresse ausgegeben. Logisch, oder? Und das ist nunmal ein Teil der zweiten Zeichenkette.

Ist ja auch völlig klar, dass man bei einer direkt im Quellcode konstant angegebenen Zeichenkette, wo man nicht einmal weiß, wo die landen wird, mit der Speicheradresse herumrechnen will. Klar ist das hier ein Fehler des Programmierers und der Compiler macht sicherlich nur das, was im Standard vorgesehen ist. Aber der gcc (3.4.5 mingw-vista special r3) hält es selbst mit gesetztem -Wall -Wextra (also sehr hohem Warnlevel) nicht im Geringsten für nötig, wenigstens eine Compilerwarnung auszugeben. (Angemessen wäre meiner Meinung nach gerade in diesem Fall schlichtweg ein Fehler. Wer wirklich auf den Pointern herumrechnen will, kann ja casten.) Natürlich hat das alles seine Richtigkeit: Der Text hat den Typ char* (also ein Pointer), und dazu kann man wunderbar einen int addieren. Was sonst sollte man denn damit machen…

Ich sage übrigens nicht, dass automatisch mehr Speicher allokiert, die Zahl in einen Text umgewandelt, an den ursprünglichen String drangehängt und ausgegeben werden muss – eine schlichte Fehlermeldung, dass „Text“ und „Zahl“ sich nicht addieren lassen, wäre völlig ausreichend.

Dieses einfache Beispiel zeigt aber, wie maschinennah man bei C/C++ programmiert. (Update: Ein weiteres, mindestens genauso fieses Beispiel siehe hier.) Dadurch, dass man so direkt auf dem Speicher arbeitet, und sich um viele Kleinigkeiten manuell kümmern muss, entsteht viel Code, mit vielen Fehlern, und „Fehler“ heißen beim Umgang mit rohem Speicher und fremden Daten desöfteren „Sicherheitslücke wegen der man sich schon beim Anschauen einer Website nen Virus fängt“. Ergänzung – zum Beispiel so (Hervorhebung von mir):

Adobe hat seinen Shockwave Player auf Version 11.5.8.612 aktualisiert und schließt damit wieder einmal zahlreiche Sicherheitslücken, von denen Angreifer mindestens 18 zum Einschleusen von Schadcode missbrauchen können. Ursache für die meisten Schwachstellen sind Speicherfehler in diversen Funktionen […]

Die meisten Exploits der letzten Jahre dürften wir tatsächlich C/C++ verdanken.

Zudem habe ich noch den Eindruck, dass entweder durch den üblichen Programmierstil und/oder durch die vielen Kleinigkeiten, die man manuell machen muss, C/C++-Programme im Vergleich zu anderen Sprachen deutlich schlechter lesbar sind.

Für mein Tool DarkLock hatte ich das „Vergnügen“, die Windows-API aus C++ heraus aufrufen zu müssen. Insbesondere die Funktion PowerDuplicateScheme gefällt mir, weil sie stellvertretend für viele andere Funktionen zeigt, wie viel „Spaß“ C++ macht. Diese erhält als Parameter die Konstante NULL (ist halt so…), einen Pointer auf die GUID des einen Schemas, und einen Pointer auf einen Pointer auf eine GUID. Richtig gelesen. Macht auch absolut Sinn, denn wenn der Pointer auf einen Nullpointer pointet, wird eine neue GUID erzeugt und der Nullpointer durch den Pointer auf die GUID ersetzt. Alles klar? (Man muss danach nur noch den Speicher richtig freigeben…)

Den Rest von DarkLock hab ich dann in C# geschrieben, einer Sprache die mehr Java als C ähnelt und deutlich weniger Schmerzen hervorruft. (Und ja, ich weiß, dass es für C durchaus Libraries gibt, die obiges Problem lösen würden.)

Es gibt sicherlich Fälle, wo C und C++ noch Sinn machen (Embedded-Systeme, Dinge die mit hoher Leistung laufen müssen, Sachen die aus sonst einem Grund derart maschinennah sein sollen, …) – für die alltägliche Programmierung von Desktopanwendungen will ich den Kram aber nicht mehr sehen. Wem meine Kritik auf viel zu niedrigem Niveau ist, darf sich gern bei Fefe bedienen.

Gibt es eigentlich einen GUI-Editor für Java, der ähnlich gut ist wie der von Visual Studio? Ich habe nämlich keine Lust, 70% der Zeit damit zu verbringen GUIs zu schreiben. Auch nett wäre, wenn die „höheren“ Sprachen eine einfache Möglichkeit bieten würden, bei Bedarf doch mal auf ein niedrigeres Level zu wechseln (mit den damit verbundenen Nachteilen), oder zumindest (gerade Java) irgendwas, um bequem mit „rohen“ Bytes (gerne durchaus in verwaltetem, geschützem Speicher!) sinnvoll arbeiten und rechnen zu können.

Werbeanzeigen