Visual C++ 6 mit Freud und Leid
« | 02 May 2020 | »Als ich anfangs der 2000er mit VB6 meine ersten “richtigen” Programme anfing, war stets das gesamte Visual Studio auch mit C++ installiert.
Gemacht habe ich damit aber nicht viel … schließlich verstand ich dieses “seltsame C++” sowieso nicht und VB war deshalb “viel besser”.
Heute bekommt dieser “seltsamste” aller C++ Compiler einen besonderen Platz bei mir eingeräumt. Und das GATE Projekt nimmt ihn offiziell in seine Supportliste auf.
Das Studio 98 kam zu einer sehr blöden Zeit auf den Markt. C++ wurde 1998
standardisiert und erklärte viele bis dahin gebräuchlichen Verhaltensweisen
als “falsch”. Microsoft C++ 6 war Teil von Studio 98 und wurde damit vor
der Standardisierung entwickelt, war damit Nicht-Standard-Konform aber wurde
dennoch bis 2002 als primärer Windows-Compiler eingesetzt und formal erst
im Jahr 2010 endgültig abgelöst.
(Wer erinnert sich noch an die Meldung “10 is the new 6”, als MSVC10 rauskam?)
Das ist natürlich gefundenes Fressen für alle Windows-Kritiker, die somit zu Recht behaupten konnten, dass Windows auf extrem wackeligen Beinen steht.
Die Workarounds in BOOST und anderen Bibliotheken für diesen Sonder-Compiler sind schon fast legendär, so “pervers” waren sie geschrieben.
Typische VC6 Problemchen
Über folgende Probleme bin ich schon mehrmals gestolpert:
new
wirft im Fehlerfall keine Exception sondern gibt einen NULL-Pointer zurück. Das kann man sogar durch einen angepasstenoperator new
fixen, aber hier streiten sich dann gerne die Libs, wer den Operator zuerst überladen darf.template
Funktionen mit void-Return Value erzeugen Fehler.
Folgender Code kompiliert nicht:Nun gut, man könnte meinen, dass es auch wenig Sinn macht einen “void” zurückgeben, aber spätestens seit dem C++03 Update und in MSVC 2003 wird dieser Code gültig. Man braucht ihn vor allem für Delegates oder andere Formen von Methoden- oder Funktions-Dispatchern.
- Variadic Macros existieren nicht.
Ärgerlich, weil manche Debugging-Macros ähnlich wieprintf
mehrere Argumente so aneinanderreihen. - Makros in Makros brauchen teils weitere Makros um zu funktionieren.
Ein Makro kann nicht ein anderes Parameter-freies Makro einbauen, nein, man braucht ein drittes Makro, dem man das gewollte Makro als Parameter übergibt, welches das Makro selbst wieder zurückgibt (bzw. dessen Auswertung). char
ist entweder zusigned char
oder zuunsigned char
identisch und kein eigener Typ. Tatsächlich sind beitemplate
Instanzen die Typenchar
,signed char
undunsigend char
insgesamt 3 unterschiedliche Typen. Nur nicht in VC6. Da sindchar
undsigned char
identisch, außer man setzt eine Compileroption, diechar
einemunsigned char
gleichsetzt.- Zwei Kopierkonstruktoren mit konstantem und nicht-konstantem Argument führen zu Fehlern.
Zugegeben, das ist in C++ generell seltsam, dass man die Kopierkonstruktoren
definieren kann. Welcher genommen wird, ist oft schwer nachvollziehbar, weil sich der konstante auch um die nicht-konstanten Aufrufe kümmern darf. VC6 erfindet aber bei einem
type(type& src);
ohne den anderen einen selbstgestricktenmemcpy()
basiertentype(type const& src);
dazu, und dann ist die Kacke meist am Dampfen. for
Schleifen dürfen in C keine Typendeklarationen einführen.
Einfor(int i = 0; ...)
ist falsch,int i;
muss vor der Schleife stehen.long long
existiert nicht, anstatt dessen haben wir__int64
Das bereitet oft die meisten Schmerzen und eine Vielzahl an Libs beinhaltet deshalb Codes wie:
… und sicher gibt es noch viel mehr, das mich entweder nicht betroffen haben, oder was ich schon verdrängt habe.
Fazit
Aus C++ Sicht ist der VC6 heute immer noch der größte Alptraum aller Zeiten,
und das liegt an vielen Codes, die damals entstanden sind und unter neuen
Compilern Probleme bereiteten.
Deshalb wird er so gut wir gar nicht mehr offiziell unterstützt.
Da das Projekt aber auf dem älteren C89 Standard aufsetzt und C++ nur einen
dünnen Layer darüber darstellt, möchte ich dennoch versuchen diesen
Dinosaurier am Leben zu erhalten.
Wenn ich einmal meine heutigen Codes in die Vergangenheit schicken kann,
sind diese vermutlich die einzigen, die damals kompilierbar gewesen wären.
Und irgendwie reizt mich dieser Gedanke.
Wenn man also ein paar Makros und typedef
s einsetzt und brav alle Typen am
Beginn der Funktion deklariert, kann man dynamisch eingebundene
Windows 10 - Features unter einem Windows 98
mit MSVC6 kompilieren und am Ende in der Azur Cloud ausführen …
Na, das nenn’ ich mal eine Challenge!