Handbuch zur dynamischen Ablaufverfolgung in Solaris

Kapitel 6 Zeichenketten

DTrace bietet Unterstützung für die Ablaufverfolgung und Manipulation von Zeichenketten. In diesem Kapitel werden sämtliche Leistungsmerkmale der Programmiersprache D zum Deklarieren und Manipulieren von Zeichenketten besprochen. Im Gegensatz zu ANSI-C besitzen Zeichenketten in D eine eigene, integrierte Typ- und Operatorunterstützung, sodass sie sich einfach und eindeutig in Tracing-Programme einbauen lassen.

Zeichenkettendarstellung

Zeichenketten werden in DTrace als Vektoren von Zeichen mit einem abschließenden Null-Byte (d. h. einem Byte mit dem Wert Null, das in der Regel in der Form '\0' geschrieben wird) dargestellt. Der sichtbare Teil einer Zeichenkette hat eine variable Länge, die von der Position des Null-Bytes abhängt. DTrace speichert jedoch jede Zeichenkette in einem Vektor festgelegter Größe, sodass alle Prüfpunkte eine einheitliche Datenmenge verfolgen. Zwar dürfen die Zeichenketten diese vordefinierte Höchstlänge nicht überschreiten, doch lässt sich die Höchstlänge im D-Programm oder in der dtrace-Befehlszeile durch Anpassung der Option strsize ändern. Weitere Informationen zu abstimmbaren DTrace-Optionen finden Sie in Kapitel 16Optionen und Tunables . Die Standardhöchstlänge für Zeichenketten beträgt 256 Byte.

Die Sprache D bietet einen expliziten string-Typ, der anstelle des Typs char * zum Verweisen auf Zeichenketten genutzt werden kann. Der Typ string ist insoweit gleichbedeutend mit einem char *, als er die Adresse einer Folge von Zeichen darstellt. Bei Anwendung auf Ausdrücke des Typs string() stellen der D-Compiler und D-Funktionen wie trace jedoch erweiterte Fähigkeiten bereit. So beseitigt der String-Typ beispielsweise die Zweideutigkeit des Typs char * für den Fall, dass Sie die tatsächlichen Byte einer Zeichenkette verfolgen müssen. In der D-Anweisung:

trace(s);

verfolgt DTrace, wenn s den Typ char * aufweist, den Wert des Zeigers s (d. h., es wird ein ganzzahliger Adresswert aufgezeichnet). In der D-Anweisung:

trace(*s);

dereferenziert der D-Compiler gemäß der Definition des Operators * den Zeiger s und verfolgt das einzelne Zeichen an jener Position. Dieses Verhalten ist grundlegend für die Manipulation von Zeichenzeigern, die entwurfsgemäß entweder auf einzelne Zeichen oder auf Vektoren mit byte-großen Ganzzahlen verweisen, die keine Zeichenketten sind und nicht mit einem Null-Byte enden. In der D-Anweisung:

trace(s);

teilt der Typ string, wenn s ein string ist, dem D-Compiler mit, dass DTrace eine Zeichenkette verfolgen soll, deren Adresse in der Variable s gespeichert ist. Außerdem können Sie lexikalische Vergleiche von Ausdrücken des Typs string durchführen. Dies wird unter Zeichenkettenvergleich beschrieben.

Konstante Zeichenketten

Konstante Zeichenketten sind von doppelten Anführungszeichen (") umgeben und erhalten vom D-Compiler automatisch den Typ string. Sie können konstante Zeichenketten beliebiger Länge definieren, die nur durch die Speicherkapazität begrenzt ist, die DTrace auf dem System nutzen darf. Das abschließende Null-Byte ( \0) wird vom D-Compiler automatisch an jede von Ihnen deklarierte konstante Zeichenkette angefügt. Die Größe eines konstanten Zeichenkettenobjekts ergibt sich aus der Byteanzahl der Zeichenkette plus einem zusätzlichen Byte für das abschließende Null-Byte.

Zeichenkettenkonstanten dürfen keine wörtlichen Zeilentrenner enthalten. Zur Angabe einer neuen Zeile innerhalb einer Zeichenkette verwenden Sie stattdessen die Ersatzdarstellung \n. Alle bereits in Tabelle 2–5 für Zeichenkonstanten definierten Sonderzeichen-Ersatzdarstellungen dürfen auch in konstanten Zeichenketten vorkommen.

Zeichenkettenzuweisung

Anders als die Zuweisung von char *-Variablen werden Zeichenketten nicht per Verweis, sondern per Wert zugewiesen. Die Zeichenkettenzuweisung erfolgt mit dem Operator =. Dabei werden die tatsächlichen Byte der Zeichenkette ab dem Quelloperanden bis zu einschließlich dem Null-Byte in die Variable auf der linken Seite kopiert, bei der es sich um den Typ string handeln muss. Sie können eine neue Variable des Typs string erzeugen, indem Sie ihr einen Ausdruck des Typs string zuweisen. So würde beispielsweise die D-Anweisung:

s = "hello";

eine neue Variable s des Typs string erzeugen und die 6 Byte der Zeichenkette "hello" in sie kopieren (5 druckbare Zeichen plus Null-Byte). Die Zeichenkettenzuweisung verhält sich analog zur C-Bibliotheksfunktion strcpy(3C) mit der Abweichung, dass sich bei Überschreiten der Speicherkapazität der Zielzeichenkette durch die Ausgangszeichenkette eine Zeichenkette ergibt, die automatisch an diesem Grenzwert abgeschnitten wird.

Einer Zeichenkettenvariable kann auch ein Ausdruck eines mit Zeichenketten verträglichen Typs zugewiesen werden. In diesem Fall erweitert der D-Compiler den Ausgangsausdruck automatisch auf den String-Typ und führt eine Zeichenkettenzuweisung durch. Der D-Compiler lässt für beliebige Ausdrücke des Typs char * oder char[n] (d. h. einen skalaren Vektor des Typs char mit beliebiger Größe) eine Erweiterung auf string zu.

Zeichenkettenumwandlung

Ausdrücke anderer Typen können explizit in den Typ string umgewandelt werden. Hierzu verwenden Sie einen Cast-Ausdruck oder wenden den speziellen Operator stringof an. Die beiden Verfahren sind äquivalent:

s = (string) Ausdruck				s = stringof ( Ausdruck )

Der Operator stringof hat eine sehr starke Bindung an den Operanden rechts neben ihm. In der Regel wird der Ausdruck zur Verdeutlichung in Klammern gesetzt, die allerdings nicht wirklich erforderlich sind.

Jeder Ausdruck skalaren Typs wie zum Beispiel Zeiger oder Ganzzahlen oder skalare Vektoradressen können in string umgewandelt werden. Ausdrücke anderer Typen wie void lassen sich nicht in string konvertieren. Wenn Sie eine ungültige Adresse fälschlicherweise in einen String-Typ umwandeln, verhindern die DTrace-Sicherheitseinrichtungen zwar eine Beschädigung des Systems oder von DTrace, doch wird unter Umständen trotzdem eine Sequenz nicht entzifferbarer Zeichen verfolgt.

Zeichenkettenvergleich

D überlädt die binären relationalen Operatoren und erlaubt ihren Einsatz für Zeichenketten- sowie Ganzzahlenvergleiche. Die relationalen Operatoren führen einen Zeichenkettenvergleich durch, wenn beide Operanden den Typ string besitzen oder wenn ein Operand ein string ist und der andere Operand, wie unter beschrieben, auf den Typ string (siehe Zeichenkettenzuweisung) erweitert werden kann. Zum Vergleichen von Zeichenketten können alle relationalen Operatoren verwendet werden:

Tabelle 6–1 Relationale Operatoren für Zeichenketten in D

<

Operand auf linker Seite ist kleiner als Operand auf rechter Seite 

<=

Operand auf linker Seite ist kleiner als oder gleich dem Operanden auf rechter Seite 

>

Operand auf linker Seite ist größer als Operand auf rechter Seite 

>=

Operand auf linker Seite ist größer als oder gleich dem Operanden auf rechter Seite 

==

Operand auf linker Seite ist gleich dem Operanden auf rechter Seite 

!=

Operand auf linker Seite ist ungleich dem Operanden auf rechter Seite 

Wie auch bei Ganzzahlen ergibt jeder Operator einen Wert des Typs int, der gleich 1 ist, wenn die Bedingung wahr ist und 0, wenn sie falsch ist.

Die relationalen Operatoren vergleichen die beiden eingegebenen Zeichenketten Byte für Byte auf ähnliche Weise wie die C-Bibliotheksroutine strcmp(3C). Jedes Byte wird so lange über seinen entsprechenden ganzzahligen Wert im ASCII-Zeichensatz (siehe ascii(5)) verglichen, bis ein Null-Byte gelesen wird oder die maximale Zeichenkettenlänge erreicht ist. Sehen Sie hier einige Beispiele für Zeichenkettenvergleiche in D und ihre Ergebnisse:

"coffee" < "espresso"

... gibt 1 (wahr) zurück 

"coffee" == "coffee"

... gibt 1 (wahr) zurück 

"coffee" >= "mocha"

... gibt 0 (falsch) zurück