Поделиться через


Выравнивание

Проблемы выравнивания в приложении ODBC обычно не отличаются от других приложений. То есть большинство приложений ODBC имеют мало проблем с выравниванием. Штрафы за отсутствие выравнивания адресов зависят от оборудования и операционной системы и могут быть незначительными, как незначительный штраф производительности или как крупный, как неустранимая ошибка во время выполнения. Поэтому приложения ODBC и переносимые приложения ODBC, в частности, должны быть осторожны, чтобы правильно выровнять данные.

Один из примеров, когда приложения ODBC сталкиваются с проблемами выравнивания, заключается в том, что они выделяют большой блок памяти и привязывают различные части этой памяти к столбцам в результирующем наборе. Это, скорее всего, происходит, когда общее приложение должно определить форму результирующего набора во время выполнения и выделить и привязать память соответствующим образом.

Например, предположим, что приложение выполняет инструкцию SELECT , введенную пользователем, и извлекает результаты из этой инструкции. Поскольку форма этого результирующего набора неизвестна при написании программы, приложение должно определить тип каждого столбца после создания результирующего набора и привязать память соответствующим образом. Самый простой способ сделать это — выделить большой блок памяти и привязать различные адреса в этом блоке к каждому столбцу. Чтобы получить доступ к данным в столбце, приложение привязывает память, привязанную к такому столбцу.

На следующей схеме показан пример результирующего набора и как блок памяти может быть привязан к нему с помощью по умолчанию типа данных C для каждого SQL типа данных. Каждый элемент "X" представляет один байт памяти. (В этом примере показаны только буферы данных, привязанные к столбцам. Это делается для простоты. В фактическом коде буферы длины и индикатора также должны быть выровнены.)

Привязка по умолчанию типа данных C к типу данных SQL

Если привязанные адреса хранятся в массиве адресов , приложение использует следующие выражения для доступа к памяти, привязанной к каждому столбцу:

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

Обратите внимание, что адреса, привязанные ко второму и третьему столбцам, начинаются с нечетных байтов, и адрес, привязанный к третьему столбцу, не делится на четыре, что является размером SDWORD. На некоторых компьютерах это не будет проблемой; на других это приведет к незначительному снижению производительности; на третьих это приведет к критической ошибке выполнения. Лучше решение — выровнять каждый присвоенный адрес по его естественной границе выравнивания. Если это значение равно 1 для UCHAR, 2 для SWORD и 4 для SDWORD, это даст результат, показанный на следующей иллюстрации, где "X" представляет используемый байт памяти, а "O" представляет байт памяти, которая не используется.

Привязка по границе натурального выравнивания

Хотя это решение не использует всю память приложения, она не сталкивается с проблемами выравнивания. К сожалению, для реализации этого решения требуется достаточное количество кода, так как каждый столбец должен быть выровнен по отдельности по своему типу. Проще всего выровнять все столбцы по размеру самой большой границы выравнивания, которая составляет 4 в примере, показанном на следующем рисунке.

Привязка по максимальной границе выравнивания

Хотя это решение оставляет более крупные отверстия, код для его реализации относительно простой и быстрый. В большинстве случаев это компенсирует потери, связанные с неиспользуемой памятью. Пример использования этого метода см. в разделе Using SQLBindCol.