Ausrichtung
Die Ausrichtungsprobleme in einer ODBC-Anwendung unterscheiden sich in der Regel nicht von denen in einer anderen Anwendung. Das heißt, die meisten ODBC-Anwendungen haben nur wenige oder keine Probleme mit der Ausrichtung. Die Strafen für nicht ausgerichtete Adressen variieren je nach Hardware und Betriebssystem und können als geringfügige Leistungseinbußen oder als schwerwiegender Laufzeitfehler auftreten. Daher sollten ODBC-Anwendungen und portable ODBC-Anwendungen insbesondere darauf achten, Daten ordnungsgemäß auszurichten.
Ein Beispiel dafür, dass BEI ODBC-Anwendungen Ausrichtungsprobleme auftreten, besteht darin, dass sie einen großen Speicherblock zuweisen und unterschiedliche Teile dieses Speichers an die Spalten in einem Resultset binden. Dies tritt höchstwahrscheinlich auf, wenn eine generische Anwendung das Shape eines Resultsets zur Laufzeit bestimmen und Speicher entsprechend zuordnen und binden muss.
Angenommen, eine Anwendung führt eine SELECT-Anweisung aus, die vom Benutzer eingegeben wurde, und ruft die Ergebnisse aus dieser Anweisung ab. Da die Form dieses Resultsets beim Schreiben des Programms nicht bekannt ist, muss die Anwendung den Typ jeder Spalte bestimmen, nachdem das Resultset erstellt wurde, und speicher entsprechend binden. Am einfachsten können Sie dies tun, um einen großen Speicherblock zuzuweisen und verschiedene Adressen in diesem Block an jede Spalte zu binden. Um auf die Daten in einer Spalte zuzugreifen, wandelt die Anwendung den an diese Spalte gebundenen Speicher um.
Das folgende Diagramm zeigt ein Beispiel-Resultset und wie ein Speicherblock mit dem standardmäßigen C-Datentyp für jeden SQL-Datentyp an ihn gebunden werden kann. Jedes "X" stellt ein einzelnes Byte des Arbeitsspeichers dar. (Dieses Beispiel zeigt nur die Datenpuffer, die an die Spalten gebunden sind. Dies geschieht aus Gründen der Einfachheit. Im tatsächlichen Code müssen auch die Längen-/Indikatorpuffer ausgerichtet werden.)
Vorausgesetzt, die gebundenen Adressen werden im Adressarray gespeichert, verwendet die Anwendung die folgenden Ausdrücke, um auf den an jede Spalte gebundenen Speicher zuzugreifen:
(SQLCHAR *) Address[0]
(SQLSMALLINT *) Address[1]
(SQLINTEGER *) Address[2]
Beachten Sie, dass die adressen, die an die zweite und dritte Spalte gebunden sind, bei ungeraden Bytes beginnen und dass die an die dritte Spalte gebundene Adresse nicht durch vier divisierbar ist, was die Größe eines SDWORD ist. Auf einigen Computern ist dies kein Problem; bei anderen wird dies zu einer leichten Leistungsstrafe führen; bei noch anderen verursacht dies einen schwerwiegenden Laufzeitfehler. Eine bessere Lösung wäre, jede gebundene Adresse an der natürlichen Ausrichtungsgrenze auszurichten. Wenn dies 1 für eine UCHAR, 2 für ein SCHWERT und 4 für ein SDWORD ist, würde dies das Ergebnis in der folgenden Abbildung geben, wobei ein "X" ein Byte des verwendeten Speichers darstellt und ein "O" ein Byte des nicht verwendeten Arbeitsspeichers darstellt.
Obwohl diese Lösung nicht den gesamten Arbeitsspeicher der Anwendung verwendet, tritt keine Ausrichtungsprobleme auf. Leider dauert es einen fairen Code, um diese Lösung zu implementieren, da jede Spalte individuell entsprechend ihrem Typ ausgerichtet werden muss. Eine einfachere Lösung besteht darin, alle Spalten an der Größe der größten Ausrichtungsgrenze auszurichten, die 4 im Beispiel in der folgenden Abbildung dargestellt ist.
Obwohl diese Lösung größere Löcher hinterlässt, ist der Code zur Implementierung relativ einfach und schnell. In den meisten Fällen wird dadurch die Strafe ausgeglichen, die im nicht genutzten Speicher bezahlt wird. Ein Beispiel, das diese Methode verwendet, finden Sie unter Verwenden von SQLBindCol.