Guia de rastreamento dinâmico Solaris

Capítulo 6 Seqüências

O DTrace oferece suporte para rastrear e manipular seqüências. Este capítulo descreve o conjunto completo dos recursos da linguagem D para declarar e manipular seqüências. Ao contrário de ANSI-C, as seqüências em D possuem o próprio tipo interno e suporte a operador, para que você possa usá-las facilmente, sem ambigüidade, nos seus programas de rastreio.

Representação de seqüência

As seqüências são representadas no DTrace como uma matriz de caracteres terminados por um byte nulo (ou seja, um byte cujo valor é zero, geralmente escrito como '\0'). A parte visível da seqüência é do tamanho da variável, dependendo do local do byte nulo, mas o DTrace armazena cada seqüência em uma matriz de tamanho fixo, para que cada teste rastreie uma quantidade consistente de dados. As seqüências não podem ultrapassar o tamanho desse limite de seqüência predefinido, mas o limite pode ser modificado em seu programa em D ou na linha de comando do dtrace, por meio do ajuste da opção strsize . Consulte o Capítulo 16Opções e ajustáveis para obter mais informações sobre opções ajustáveis do DTrace. O limite de seqüência padrão é 256 bytes.

A linguagem D oferece um tipo string específico em vez de usar o tipo char * para fazer referência a seqüências. O tipo string é equivalente a char * no sentido de que é o endereço de uma seqüência de caracteres, porém o compilador e as funções de D, como trace(), oferecem recursos avançados quando aplicados a expressões do tipo string. Por exemplo, o tipo string remove a ambigüidade do tipo char * quando você precisa rastrear os bytes reais de uma seqüência. Na declaração de D:

trace(s);

se s for do tipo char *, o DTrace rastreará o valor do ponteiro s (ou seja, ele rastreará um valor de endereço de inteiro). Na declaração de D:

trace(*s);

por definição do operador *, o compilador D cancelará a referência do ponteiro s e rastreará o único caractere nesse local. Esses comportamentos são essenciais para permitir que você manipule os ponteiros de caractere que por definição se referem a caracteres únicos, ou a matrizes de inteiros de tamanho de byte que não são seqüências e não terminam com um byte nulo. Na declaração de D:

trace(s);

se s for do tipo string, o tipo string indicará para o compilador de D que você deseja que o DTrace rastreie uma seqüência de caracteres terminada em nulo, cujo endereço é armazenado na variável s. Você também pode realizar uma comparação lexical de expressões do tipo string, conforme descrito em Comparação de seqüências.

Constante de seqüências

As constantes de seqüências são colocadas entre aspas duplas (") e são atribuídas automaticamente ao tipo string pelo compilador de D. Você também pode definir constantes de seqüências de qualquer tamanho, limitadas apenas pela quantidade de memória que o DTrace pode consumir em seu sistema. O byte nulo de terminação ( \0) é adicionado automaticamente pelo compilador de D a quaisquer constantes de seqüências declaradas por você. O tamanho de um objeto de constante de seqüências é o número de bytes associado à seqüência mais um byte adicional para o byte nulo de terminação.

Uma constante de seqüência talvez não contenha um caractere de nova linha literal. Para criar seqüências que contêm novas linhas, use a seqüência de escape \n em vez de uma nova linha literal. As constantes de seqüências também contêm quaisquer uma das seqüências de escape de caractere especial definidas para constantes de caracteres na Tabela 2–5.

Atribuição de seqüências

Ao contrário da atribuição de variáveis char *, as seqüências são copiadas por valor, não por referência. A atribuição de seqüências é realizada por meio do operador = e copia os bytes reais da seqüência do operando de origem, incluindo o byte nulo, para a variável do lado esquerdo, que deve ser do tipo string. Você pode criar uma nova variável do tipo string atribuindo-a a uma expressão do tipo string. Por exemplo, a declaração de D:

s = "hello";

criaria uma nova variável s do tipo string e copiaria os 4 bytes da seqüência "olá" para ela (3 caracteres imprimíveis mais o byte nulo). A atribuição de seqüências é análoga à função de biblioteca de C strcpy(3C), exceto que se a seqüência de origem exceder o limite do armazenamento da seqüência de destino, a seqüência resultante será truncada automaticamente nesse limite.

Você também pode atribuir a uma variável de seqüência uma expressão de um tipo que seja compatível com seqüências. Neste caso, o compilador de D promove automaticamente a expressão de origem para o tipo string e realiza uma atribuição de seqüências. O compilador de D permite que qualquer expressão do tipo char * ou do tipo char[n] (ou seja, uma matriz escalar de char de qualquer tamanho), seja promovida para string.

Conversão de seqüências

Expressões de outros tipo podem ser convertidas explicitamente para o tipo string por meio de uma expressão de conversão ou através da aplicação do operador especial stringof, que têm significados equivalentes:

s = (string) expression				s = stringof ( expression )

O operador stringof se vincula muito fortemente ao operando do seu lado direito. Geralmente, os parênteses são usados para cercar a expressão por motivo de clareza, embora eles não sejam estritamente necessários.

Qualquer expressão que seja de um tipo escalar, tal como um ponteiro, um inteiro, ou um endereço de matriz escalar, pode ser convertida para string. As expressões de outros tipos, tal como void, não podem ser convertidas para string. Se você converter erradamente um endereço inválido em uma seqüência, os recursos de segurança do DTrace evitarão que você danifique o sistema ou o DTrace, mas talvez você termine rastreando uma seqüência de caracteres indecifráveis.

Comparação de seqüências

D sobrecarrega os operadores relacionais binários e permite que eles sejam usados para comparações de seqüências, assim como para comparações de inteiros. Os operadores relacionais fazem a comparação de seqüências sempre que ambos os operandos forem do tipo string, ou quando um operando for do tipo string e o outro operando puder ser promovido para o tipo string, conforme descrito em Atribuição de seqüências. Todos os operadores relacionais podem ser usados para comparar seqüências:

Tabela 6–1 Operadores relacionais de D para seqüências

<

o operando esquerdo é menor que o operando direito 

<=

o operando esquerdo é menor ou igual ao operando direito 

>

o operando esquerdo é maior que o operador direito 

>=

o operando esquerdo é maior ou igual ao operando direito 

==

o operando esquerdo é igual ao operando direito 

!=

o operando esquerdo não é igual ao operando direito 

Como nos inteiros, cada operador é avaliado com um valor de tipo int que é igual a um, se a condição for verdadeira, ou zero se for falsa.

Os operadores relacionais comparam as duas seqüências de entrada byte por byte, semelhante à rotina de biblioteca de C strcmp(3C). Cada byte é comparado através do seu valor de inteiro correspondente no conjunto de caracteres ASCII, conforme mostrado em ascii(5), até que um byte nulo seja lido ou o tamanho máximo de seqüência seja alcançado. Alguns exemplos de comparações de seqüências de D e seus resultados:

"café" < "expresso"

... retorna 1 (verdadeiro) 

"café" == "café"

... retorna 1 (verdadeiro) 

"café" >= "mocha"

... retorna 0 (falso)