Alinhamento

Os problemas de alinhamento em um aplicativo ODBC geralmente não são diferentes dos de qualquer outro aplicativo. Ou seja, a maioria dos aplicativos ODBC tem poucos ou nenhum problema com o alinhamento. As penalidades por não alinhar os endereços variam de acordo com o hardware e o sistema operacional e podem ser tão pequenas quanto uma pequena penalidade de desempenho ou tão grandes quanto um erro fatal de tempo de execução. Portanto, os aplicativos ODBC e os aplicativos ODBC portáteis, em particular, devem ter o cuidado de alinhar os dados corretamente.

Um exemplo de quando os aplicativos ODBC encontram problemas de alinhamento é quando eles alocam um grande bloco de memória e vinculam diferentes partes dessa memória às colunas em um conjunto de resultados. É mais provável que isso ocorra quando um aplicativo genérico precisa determinar a forma de um conjunto de resultados em tempo de execução e alocar e vincular a memória de acordo.

Por exemplo, suponha que um aplicativo execute uma instrução SELECT inserida pelo usuário e obtenha os resultados dessa instrução. Como a forma desse conjunto de resultados não é conhecida quando o programa é escrito, o aplicativo deve determinar o tipo de cada coluna depois que o conjunto de resultados é criado e vincular a memória de acordo. A maneira mais fácil de fazer isso é alocar um grande bloco de memória e associar endereços diferentes nesse bloco a cada coluna. Para acessar os dados em uma coluna, o aplicativo lança a memória vinculada a essa coluna.

O diagrama a seguir mostra um exemplo de conjunto de resultados e como um bloco de memória pode ser vinculado a ele usando o tipo de dados C padrão para cada tipo de dados SQL. Cada "X" representa um único byte de memória. (Este exemplo mostra apenas os buffers de dados vinculados às colunas, para simplificar. No código real, os buffers de comprimento/indicador também devem ser alinhados)

Binding by default C data type to SQL data type

Supondo que os endereços vinculados estejam armazenados na matriz Endereço, o aplicativo usa as seguintes expressões para acessar a memória vinculada a cada coluna:

(SQLCHAR *)       Address[0]  
(SQLSMALLINT *)   Address[1]  
(SQLINTEGER *)    Address[2]  

Observe que os endereços vinculados à segunda e à terceira colunas começam em bytes ímpares e que o endereço vinculado à terceira coluna não é divisível por quatro, que é o tamanho de um SDWORD. Em alguns computadores, isso não será um problema; em outros, causará uma pequena queda no desempenho; em outros ainda, causará um erro fatal de tempo de execução. Uma solução melhor seria alinhar cada endereço vinculado em seu limite de alinhamento natural. Supondo que isso seja 1 para um UCHAR, 2 para um SWORD e 4 para um SDWORD, o resultado seria o mostrado na ilustração a seguir, em que um "X" representa um byte de memória usado e um "O" representa um byte de memória não usado.

Binding by natural alignment boundary

Embora essa solução não use toda a memória do aplicativo, ela não apresenta nenhum problema de alinhamento. Infelizmente, é preciso uma boa quantidade de código para implementar essa solução, pois cada coluna deve ser alinhada individualmente de acordo com seu tipo. Uma solução mais simples é alinhar todas as colunas no tamanho do maior limite de alinhamento, que é 4 no exemplo mostrado na ilustração a seguir.

Binding by largest alignment boundary

Embora essa solução deixe buracos maiores, o código para implementá-la é relativamente simples e rápido. Na maioria dos casos, isso compensa a penalidade paga em memória não utilizada. Para ver um exemplo que usa esse método, consulte Usando SQLBindCol.