Delen via


Uitlijning

De uitlijningsproblemen in een ODBC-toepassing zijn over het algemeen niet anders dan in een andere toepassing. Dat wil gezegd, de meeste ODBC-toepassingen hebben weinig of geen problemen met uitlijning. De boetes voor het niet uitlijnen van adressen variëren met de hardware en het besturingssysteem en kunnen net zo klein zijn als een lichte prestatiestraf of als een fatale runtimefout. Daarom moeten ODBC-toepassingen en draagbare ODBC-toepassingen met name voorzichtig zijn om gegevens correct uit te lijnen.

Een voorbeeld van wanneer ODBC-toepassingen uitlijningsproblemen ondervinden, is wanneer ze een groot geheugenblok toewijzen en verschillende delen van dat geheugen binden aan de kolommen in een resultatenset. Dit is waarschijnlijk het geval wanneer een algemene toepassing de vorm van een resultatenset tijdens runtime moet bepalen en het geheugen dienovereenkomstig moet toewijzen en binden.

Stel dat een toepassing een SELECT-instructie uitvoert die door de gebruiker is ingevoerd en de resultaten van deze instructie ophaalt. Omdat de vorm van deze resultatenset niet bekend is wanneer het programma is geschreven, moet de toepassing het type van elke kolom bepalen nadat de resultatenset is gemaakt en het geheugen dienovereenkomstig binden. De eenvoudigste manier om dit te doen, is door een groot geheugenblok toe te wijzen en verschillende adressen in dat blok aan elke kolom te koppelen. Om toegang te krijgen tot de gegevens in een kolom, wordt het geheugen dat aan die kolom is gekoppeld, door de toepassing omgezet.

In het volgende diagram ziet u een voorbeeld van een resultatenset en hoe een geheugenblok kan worden gebonden met behulp van het standaard-C-gegevenstype voor elk SQL-gegevenstype. Elke X vertegenwoordigt één byte van het geheugen. (In dit voorbeeld worden alleen de gegevensbuffers weergegeven die zijn gebonden aan de kolommen. Dit gebeurt voor het gemak. In de werkelijke code moeten ook de lengte/indicatorbuffers worden uitgelijnd.)

Standaard C-gegevenstype binden aan SQL-gegevenstype

Ervan uitgaande dat de afhankelijke adressen zijn opgeslagen in de adresmatrix , gebruikt de toepassing de volgende expressies om toegang te krijgen tot het geheugen dat aan elke kolom is gebonden:

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

U ziet dat de adressen die zijn gebonden aan de tweede en derde kolom beginnen op oneven bytes en dat het adres dat is gebonden aan de derde kolom niet deelbaar is door vier, wat de grootte is van een SDWORD. Op sommige computers is dit geen probleem; op andere, zal het een lichte prestatiestraf veroorzaken; op nog andere, zal het een fatale runtime-fout veroorzaken. Een betere oplossing is om elk gebonden adres uit te lijnen op zijn natuurlijke uitlijningsgrens. Ervan uitgaande dat dit 1 is voor een UCHAR, 2 voor een ZWAARD en 4 voor een SDWORD, zou dit het resultaat geven dat wordt weergegeven in de volgende afbeelding, waarbij een 'X' een byte van het geheugen vertegenwoordigt die wordt gebruikt en een 'O' een byte van het geheugen vertegenwoordigt die niet wordt gebruikt.

Binding op natuurlijke uitlijningsgrens

Hoewel deze oplossing niet al het geheugen van de toepassing gebruikt, treedt er geen uitlijningsproblemen op. Helaas duurt het redelijk veel code om deze oplossing te implementeren, omdat elke kolom afzonderlijk moet worden uitgelijnd op basis van het type. Een eenvoudigere oplossing is om alle kolommen uit te lijnen op de grootte van de grootste uitlijningsgrens. Dit is 4 in het voorbeeld dat in de volgende afbeelding wordt weergegeven.

Binding door grootste uitlijningsgrens

Hoewel deze oplossing grotere gaten laat, is de code om deze te implementeren relatief eenvoudig en snel. In de meeste gevallen compenseert dit het nadeel van ongebruikt geheugen. Zie SqlBindCol gebruiken voor een voorbeeld dat deze methode gebruikt.