Aus Linux-Magazin 06/2006

GCC 4.1: Features und Benchmark

NASA

Der GNU-Compiler GCC hat neben dem Dialekt Objective C++ eine Menge Neuerungen an Bord. Ein handgeschriebener Parser für C und Verwandte soll die erste Stufe der Übersetzung beschleunigen, andere Erweiterungen die Sicherheit eigener Programme verbessern.

Mit nur einer Woche Verspätung erblickte GCC 4.1 das Licht der Welt [1]. Release-Manager Mark Mitchell musste kurz vor dem geplanten Veröffentlichungsdatum die Release noch etwas verzögern, da für PowerPC die Unterstützung von 128-Bit-Floating-Point-Berechnungen eingearbeitet werden sollte, weil diese für die kommende Glibc 2.4 wichtig sind.

Handgeschriebener Parser

Zu den großen Änderungen gehört, dass der GCC den mit der letzten Version neu eingeführten C++-Parser nun auch für C und Objective C verwendet. Dieser handgeschriebene, also nicht mit einem klassischen Parser-Generator wie Bison oder Yacc generierte, Recursive-Descent-Parser ist schneller und soll sogar langfristig besser zu warten sein.

Apple hat den GCC unter Mac OS X schon seit längerem mit der Fähigkeit ausgestattet, Objective C mit C++-Code zu mischen. Objective C ist eine Alternative zu C++, die Objektorientierung mit einer Smalltalk-ähnlichen Syntax und dynamischer Typisierung und Introspektion bietet. Dafür fehlen moderne C++-Konstrukte wie Templates oder Namensräume. Mit Objective C++ ist es nun möglich, solche C++-Features mit Objective C zu mischen oder einfach nur C++-Bibliotheken aus Objective-C-Code heraus zu verwenden.

Die GCC-Entwickler haben auch den Stack Smashing Protector (SSP) integriert, den IBM entwickelt hat und der seit längerer Zeit als Add-on-Patch zur Verfügung steht [2]. Mit SSP-Support übersetzte Programme ändern die Reihenfolge von Variablen auf dem Stack, um das versehentliche, aber auch das absichtliche Verändern von Pointern zu verhindern. Mit SSP lassen sich Funktionen instrumentieren, um Buffer Overflows zu erkennen.

Stark erweitert haben die GCC-Programmierer auch die Java-Bibliothek, die umfangreiche Fähigkeiten des Java-API implementiert, inklusive der Grafik-Toolkits AWT und Swing. Die Java-Änderungen alleine füllen über ein Drittel des Changelog-Protokolls [3]. GCJ und GNU Classpath erlauben es inzwischen, die in Java geschriebene Entwicklungsumgebung Eclipse ohne Codemodifikationen zu übersetzen.

Die neuen Optimierungen, die auf der in 4.0 eingeführten Tree-SSA-Infrastruktur aufbauen (siehe [4]), arbeiten nun auch über Funktionsgrenzen hinweg. Damit erkennen sie zuverlässiger nicht verwendete Codebereiche, mögliche Kandidaten für das Inlinen von Code sowie Variablen, die vollständig durch Optimierungen entfernt wurden. Weiter verbessert haben die Entwickler zudem die automatische Vektorisierung, die Schleifen auf prozessorspezifische Vektoreinheiten wie SSE (bei Intel/AMD) und Altivec (bei PowerPC) abbildet.

Altlasten entsorgt

Wie bereits in den letzten Versionen entfallen GNU-Erweiterungen der standardisierten Sprachen, um für bessere Portabilität von Anwendungen auf andere Plattformen und Compiler zu sorgen. Betroffen sind diesmal zum Beispiel C++-Friend-Deklarationen direkt in Klassen:

struct a {
  friend void f() {
    ...
  }
};

Mit GCC 4.1 muss der C++-Programmierer die Friend-Funktion standardkonform außerhalb der Klasse definieren:

struct a {
  friend void f();
}
void f() {
  ...
}

Ein weiteres Modernisierungsopfer sind überspezifizierte Namensbereiche (Extra Qualification), die sich in einer Vielzahl von C++-Programmen finden, wie auch eine Analyse von Debian-Programmierer Martin Michlmayr beweist [5].

class b {
  void b::f ();
};

Auf solche Konstrukte reagiert der GNU-Compiler nun mit »error: extra qualification ‘b::’ on member ‘f’«. Abhilfe schafft in diesem Beispiel das Entfernen von »b::« vor den Klassenmethoden.

Wie für die früheren Artikel über den GNU-Compiler ([4], [5]) hat der Autor auch dieses Mal wieder mit Open Bench nachgemessen, wie sich der aktuelle Compiler im Vergleich zu den vorherigen Versionen schlägt (siehe Kasten “Benchmarks”). Auf Wunsch einiger Leser hat er diesmal auch die Zeiten für »-O0« gemessen, was allerdings die Dynamik der Diagramme vergrößert. Außerdem wurde das bisher für den Benchmark genutzte Athlon-System zugunsten eines AMD64 Turion64 ausgemustert.

Optimierungen bringen wenig

Die neuen GCC-Versionen übersetzen mit ausgeschalteter Optimierung deutlich schneller. So bietet sich »-O0« gerade für den Edit-Compile-Zyklus während der Entwicklung an. Am deutlichsten ist die Wirkung der Optimierungen in den C++-Tests Botan und Tramp3d zu erkennen: 25 Prozent schneller bei »O2«, über 40 Prozent bei »O3« im Fall von Botan. Die Resultate der klassischen C-Benchmarks sind eher gemischt, wie die Werte in Abbildung 1 zeigen.

Abbildung 1: Laufzeiten der von den GCC-Versionen 3.4, 4.0 und 4.1 und vom Intel-Compiler ICC übersetzten Benchmark-Programme. Hinter den Compiler-Versionen stehen die verwendeten Optimierungsschalter. Die Unterschiede zwischen den verschiedenen Optimierungsstufen sind gering.

Abbildung 1: Laufzeiten der von den GCC-Versionen 3.4, 4.0 und 4.1 und vom Intel-Compiler ICC übersetzten Benchmark-Programme. Hinter den Compiler-Versionen stehen die verwendeten Optimierungsschalter. Die Unterschiede zwischen den verschiedenen Optimierungsstufen sind gering.

Betrachtet man die Übersetzungszeiten (Abbildung 2), ist darin der Mehraufwand zu entdecken, den die GCC-Compiler betreiben, sobald der Benutzer mehr Optimierungen einschaltet. Nicht immer schlägt sich dieser Aufwand positiv in den resultierenden Laufzeiten der optimierten Benchmarkprogramme nieder. Optimistisch stimmt, dass die 4.1-Version zumindest den anspruchsvollen C++-Benchmark Tramp3d deutlich schneller kompiliert als die Vorgängerin.

Abbildung 2: Die Übersetzungszeiten der GCC-Versionen 3.4, 4.0 und 4.1 und des Intel-Compilers im Vergleich. Sie weichen im Gegensatz zu den Laufzeiten aus Abbildung 1 stark voneinander ab. Am aufwändigsten ist tendenziell die Optimierung von Schleifen mit »-loops«.

Abbildung 2: Die Übersetzungszeiten der GCC-Versionen 3.4, 4.0 und 4.1 und des Intel-Compilers im Vergleich. Sie weichen im Gegensatz zu den Laufzeiten aus Abbildung 1 stark voneinander ab. Am aufwändigsten ist tendenziell die Optimierung von Schleifen mit »-loops«.

Mehr Sicherheit

Wie bereits erwähnt ermöglicht der IBM Stack Smashing Protector das Erkennen von Buffer Under- oder Overflows. Dazu legt er nahe der Rücksprungadresse auf dem Stack einen zufälligen Wert aus »/dev/urandom« ab oder, falls nicht verfügbar, die terminierende Zeichenkette »

Fehler eingebaut

Wer das Programm aus Listing 1 kompiliert und ausführt, erhält die Fehlermeldung »*** stack smashing detected ***: ./ssp-test terminated«. Die alternative Zeichenfolge macht es Angreifern etwas schwerer, schädlichen Code in Form von Skripten einzuschleusen. Der Kommandozeilenparameter »-fstack-protector« des GCC aktiviert den Schutz.

Listing 1:
»ssp-text.c«
01 int f () {
02   char a [200];
03   char* b = a;
04   int i;
05   for (i = 0;
06        i < 201; ++i)
07     a[i] = i;
08 }
09 
10 int main () {
11   f ();
12 }

Etwas weiter als SSP geht eine mit GCC 4.0 eingeführte Technik, die die meisten Pointerzugriffe in C und C++ überprüft. Dieser Mudflap genannte Mechanismus instrumentiert während der Kompilierung Speicherzugriffe abhängig von ihrer Art (Feldzugriff oder Pointer-Dereferenzierung) und nach Vorbedingungen, die der Compiler zu diesem Zeitpunkt bereits ermittelt hat. Beispielsweise können durch so genannte Constant Propagation einige der Checks entfallen.

Mudflap überwacht STDIO

Zur Laufzeit in Libmudflap enthaltene Funktionen überprüfen diese Zugriffe auf ihre Gültigkeit. Gegebenfalls wird in kritischen Fällen das Programm beendet. Libmudflap testet außerdem auf viele Standard-C-Funktionen, die Speicher überschreiben können. Dazu gehören »mem*«, »str*«, »*put*«, »*get*« und viele weitere.

Zur Verwendung von Mudflap müssen alle Dateien mit »-fmudflap« übersetzt und mit »-lmudflap« gelinkt sein. Das kleine C-Testprogramm in Listing 2 greift lediglich ein Byte hinter der Feldgrenze des Array »a« zu. Die Überschreitung zeigt Mudflap korrekt mit Angabe des Variablennamens an (Listing 3).

Da Mudflap sehr viele Speicherzugriffe überprüft, kommt es beim Einsatz im Gegensatz zu dem kaum bemerkbaren SSP zu teilweise erheblichen Performance-Einbußen. Somit richtet sich Mudflap hauptsächlich an jene Entwickler, die beim Test von Software schneller und früher als sonst potenziell kritische Fehler finden.

Listing 2:
»mudflap-test.c«
01 int main () {
02   char a [200];
03   char* b = a;
04   printf ("%cn", b[200]);
05 }
Listing 3:
Mudflap-Ausgabe
01 mudflap violation 1 (check/read): time=1143457945.900790 ptr=0x7fffffffae78 size=1
02 pc=0x2aaaaabcd2c1 location=`mudflap-test.c:6 (main)'
03       /usr/lib64/libmudflap.so.0(__mf_check+0x41) [0x2aaaaabcd2c1]
04       ./mudflap-testt(main+0xd1) [0x4009f9]
05       /lib64/libc.so.6(__libc_start_main+0xf4) [0x2aaaaae8bea4]
06 Nearby object 1: checked region begins 1B after and ends 1B after
07 mudflap object 0x603c20: name=`mudflap-test.c:4 (main) a'
08 bounds=[0x7fffffffadb0,0x7fffffffae77] size=200 area=stack check=0r/0w liveness=0
09 alloc time=1143457945.900783 pc=0x2aaaaabcc711
10 number of nearby objects: 1

Was kommt

Unter den externen Projekten, die in GCC 4.2 einfließen sollen [7], befinden sich OpenMP [8] und Spracherweiterungungen für C, C++ und Fortran, um explizit Möglichkeiten der Parallelisierung vorzugeben. Somit wird der GCC die jüngst entstanden Lücken zu kommerziellen Compilern schließen. (ofr/csc)

Benchmarks
Bei den Benchmarks setzte der Autor wieder auf den in den letzten GCC-Artikeln verwendeten Open Bench, der es inzwischen sogar bis in die Benchmarkliste der GCC-Homepage geschafft hat [9].

Dabei gab es ein paar Umstellungen: C-Botan wurde nochmals auf die etwas aktuellere Version 1.4.12 umgestellt und der kaum auf unterschiedliche Compiler reagierende Libmad-Test entfiel zu Gunsten des Open-Source-MP3-Encoders Lame.

Da auch noch einige andere Open-Source-Entwickler an einem freien, SPEC-ähnlichen Benchmark interessiert sind, wird vermutlich noch dieses Jahr eine erste Referenzversion von Open Bench für zukünftige Vergleiche eingefroren. Kommentare und Mithelfer sind jederzeit willkommen.

Infos
[1] GCC-Homepage: [http://gcc.gnu.org]

[2] Stack Smashing Protector (SSP): [http://www.trl.ibm.com/projects/security/ssp]

[3] Veränderungen bei GCC 4.1: [http://gcc.gnu.org/gcc-4.1/changes.html]

[4] René Rebe, “Wettrennen, Neuerungen in GCC 4.0”: Linux-Magazin 07/05, S. 100

[5] Debian mit GCC 4.1 übersetzen – ein Erfahrungsbericht: [http://gcc.gnu.org/ml/gcc/2006-03/msg00740.html]

[6] Mudflap: [http://gcc.fyxm.net/summit/2003/mudflap.pdf]

[7] GCC 4.2, Planungen: [http://gcc.gnu.org/wiki/GCC 4.2 Projects]

[8] OpenMP: [http://www.openmp.org/drupal/mp-documents/spec25.pdf]

[9] Open Bench: [http://www.exactcode.de/oss/openbench/]

Der Autor
René Rebe studiert Informatik an der TFH-Berlin und hat Linux leider erst 1997 entdeckt. Er arbeitet bei Projekten wie T2 und Sane mit.

Copyright © 2002 Linux New Media AG

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben