Delphi 7 im Vergleich zu 2009 (& 2010) Rekordgrößen

8

Ich habe ein komisches Problem, wenn ich Code von Delphi 7 in 2010 umwandle. Es hat mit Datensätzen zu tun. Der unten definierte Datensatz ist in D7 432 Bytes und in D2009 (und 2010) 496. Ich weiß, dass es eine einfache Lösung ist, einen gepackten Datensatz zu erstellen, dann kommen alle Versionen auf 426 Bytes ... Wir haben jedoch Daten gespeichert, wo wir den Datensatz gestreamt haben, und jetzt versuchen wir, diese Ströme mit einer neueren Sprache zu lesen.

%Vor%

Bei der Untersuchung dieses Problems habe ich einen weiteren Datensatz erstellt, und aus welchen Gründen auch immer sind die Größen gleich? Der Datensatz ist kleiner, hat jedoch die gleichen Datentypen. aber es kommt in allen Versionen der Sprache gleich groß raus.

%Vor%

Hat jemand einen Einblick, warum ein Datensatz so verschieden ist und der andere derselbe ist? Etwas, was mit den Randlinienausrichtungen in Delphi zu tun hat. Aber was hat sich von einer Version zur nächsten so drastisch verändert?

    
Jason Nethercott 08.07.2010, 17:43
quelle

5 Antworten

14

Nun, das erste Problem besteht darin, dass Sie einen nicht gepackten Datensatz auf der Festplatte gespeichert haben. Das Packen von Feld und Array kann zwischen Produktfreigaben geändert werden, da das Layout im Speicher normalerweise außerhalb des Prozesses nicht sichtbar ist. Du hast diese Regel gebrochen.

Wenn sich die Standardwerte für das Padding zwischen Delphi 7 und Delphi 2009 geändert haben, finden Sie heraus, was die Standardwerte in D7 waren, und legen Sie die Standardeinstellungen in Delphi 2009 fest.

Überprüfen Sie auch die Array-Packungsvorgabe. Ich kann mich nicht erinnern, ob es dafür eine separate Einstellung gibt.

Sehen Sie sich Ihre Datensatzstruktur in Delphi 2009 in der Debug-Speicheransicht an. Einige oder alle der zusätzlichen Größe können auf das Auffüllen des Datensatzes selbst zurückzuführen sein (nicht auf die Felder darin), so dass die Array-Elemente bei der Verwendung des Datensatzes in einem Array auf schnellen Maschinengrenzen liegen.

Wenn nichts davon hilft, erstellen Sie in D2009 einen temporär gepackten Datensatztyp und fügen Sie manuell Byte-Füllfelder zwischen die tatsächlichen Datenfelder ein, bis die Datensatzgröße und die Feldausrichtung dem D7-Layout entsprechen. Es ist nicht nur Größe, es ist Feldausrichtungen. Lesen Sie Ihre alte Datendatei mit diesem temporär gepackten Datensatz. Übertragen Sie dann die Daten Feld für Feld in D2009 in Ihren "echten" Datensatztyp und schreiben Sie eine neue Datei aus.

Und wenn Sie schon dabei sind, packen Sie diesen Aufnahmetyp in D2009, damit dies nicht wieder passiert.

    
dthorpe 08.07.2010 18:05
quelle
7

Ich glaube, Sie haben eine Funktion getroffen. Ich konnte nicht eine vernünftige Größe mit Ihrem TToTry mit D2007 bekommen, also musste ich Feldadressen mit dem Debugger nachschlagen;

Erstens, Größe des unteren Datensatzes,

%Vor%

ist 128 (32 * 4). Dies wird erwartet, da ein Extended 10 Bytes entspricht, 30 Bytes auf 32 Bytes ausgerichtet wären.

Aber die Größe dieses Datensatzes,

%Vor%

ist 120 (30 * 4). Dies ist sicherlich unerwartet - Felder sollten immer noch an einer 8-Byte-Grenze ausgerichtet sein.

(Ich habe keine D7 zu überprüfen, aber mein Denken ist das :) Nun wissen wir also, dass gruppierte Felder gepackt sind. Daraus folgt, dass die Ausrichtung auf D7 8 Byte beträgt und Ihr Datensatz fast gepackt ist;

%Vor%

Der Compiler füllt 6 Bytes auf die letzte Gruppe auf, um ein Vielfaches von 8 zu bekommen, und dann erhalten Sie 40 + 40 + 16 + 336 = 432 Bytes.

Mit D2009 / D2010 deklarieren Sie entweder jedes Feld, ohne es zu gruppieren, oder das Verhalten wird geändert. So oder so packen Sie Ihren Datensatz und fügen Sie am Ende ein 6-Byte-Array-Dummy-Feld hinzu, und Sie sollten gut gehen.

Wenn das nicht funktioniert, schauen Sie sich die Feldadressen Ihres Datensatzes mit D7 an, erstellen Sie dann ein exaktes Duplikat auf D2009, indem Sie einen gepackten Datensatz verwenden und nach Bedarf Dummy-Felder verwenden, nachdem Sie Ihre gespeicherten Daten importiert haben die Dummy-Felder.

-
Ich habe ein solches Verhalten noch nie gewusst und kann es nirgendwo dokumentiert finden. Dennoch ist es so etwas wie ein Feature, dass ich zögere es einen Fehler zu nennen. Ich weiß nicht, ob das Verhalten bei D2009 oder D2010 das gleiche ist. Testen Sie, ob es so ist. Wenn dies der Fall ist, um erwartete Ergebnisse zu erzielen - keine halbgepackten Datensätze zu haben -, seien Sie nicht faul und deklarieren Sie jedes einzelne Feld für nicht gepackte Datensätze.

    
Sertac Akyuz 09.07.2010 00:10
quelle
3

Ich weiß, dass dies ein alter Post ist, aber ich habe gestern dasselbe Problem mit Delphi XE2 bekommen. Ich habe mehrere getippte Dateien, die mit einer Turbo Delphi 2006 App geschrieben wurden, und ich habe auch den Fehler gemacht, keine gepackten Datensätze zu verwenden. Meine Situation wurde komplizierter, weil ich Datensätze mit variabler Länge verwendete (so nennen wir sie in der z / OS-Welt, nicht 100% sicher von Delphi), sodass die falsche Ausrichtung dazu führte, dass die Datensatzschlüssel-Tags nicht eintrafen das korrekte Feld, wodurch keiner der Sub-Datensätze an der richtigen Stelle ist, wodurch die gesamte Datei unbrauchbar wird.

Was ich entdeckt habe, ist, dass Sie die Anweisungen des Alignment-Compilers nur auf einen bestimmten Code-Block anwenden können. Außerdem habe ich dieses kleine Juwel entdeckt: {$OLDTYPELAYOUT ON}

%Vor%

Ich lege die Direktive nur um den Master-Datensatz, der in die Datei geschrieben und gelesen wird, nicht um die Sub-Record-Definitionen herum. Das hat mein Problem gelöst, und ich kann jetzt in XE2 kompilieren und meine TD2006-Dateien lesen. Das nächste Mal werde ich gepackte Datensätze verwenden (oder besser SQLite). Aber ich dachte, ich würde dies teilen, da diese Seite mir seit Jahren unermesslich geholfen hat.

Sie können mehr über $ OLDTYPELAYOUT hier lesen: Ссылка . By the way, der erste, der es behoben hat, war {$A4} , aber als ich {$OLDTYPELAYOUT ON} entdeckte, habe ich es umgestellt, um das zu benutzen, da es offensichtlicher ist.

    
Jeff 22.10.2013 12:01
quelle
2

Ich glaube, die Standardausrichtung wurde erweitert. Geben Sie Ausrichtung 4 in den späteren Versionen an und prüfen Sie, ob die Ausrichtung Ihren Vorstellungen entspricht.

Für die Zukunft sollten Sie sicherstellen, dass jeder Datensatz, der auf die Festplatte geschrieben wird, gepackt gespeichert wird, damit Sie nicht auf diese Weise gebrannt werden.

Edit: Da keine der Alignments funktioniert (was mich überrascht), würde ich zum Original zurückkehren und herausfinden, wie es wirklich ausgerichtet ist. Füllen Sie den Datensatz mit etwas wie $ FF, legen Sie die Daten und schreiben Sie es aus - sehen Sie, wo die $ FFs überlebten. Nehmen Sie den neuen Datensatz, machen Sie ihn gepackt und fügen Sie Füllstoffe hinzu, die mit der Füllung im alten Datensatz übereinstimmen.

Eine Sache: Ist das eigentlich nur ein Rekord? In den alten Tagen habe ich Objekte als gefälschte Datensätze mit Vererbung verwendet - oops, an der Stelle der Vererbung wurde die normale Ausrichtung angewendet und ich konnte es nicht stoppen. Ich musste dann vor den Daten auffüllen, damit die erzwungene Ausrichtung meine Daten nicht unterbricht. (Dies ging zu einer API, es HAD richtig zu sein, ich konnte die Felder nicht unabhängig verarbeiten.)

    
Loren Pechtel 08.07.2010 18:00
quelle
2

Die Anwendung der Anweisung {$ A8} bedeutet nicht, dass alle Datensatzfelder an der 8-Byte-Grenze ausgerichtet sind - der Compiler verwendet eine andere Ausrichtungsstrategie. Zum Beispiel die Größe von

%Vor%

ist 8 Bytes in Delphi 2009, weil der Compiler den 2-Byte-Wert an der 2-Byte-Grenze, den 4-Byte-Wert an der 4-Byte-Grenze ausrichtet und die einzige tatsächliche Ausrichtung im obigen Beispiel ist Bytegrenze.

Wie bei der ursprünglichen Frage, was sich zwischen Delphi 7 und Delphi 2009 geändert hat - lesen Sie die Antwort von Sertac Akyuz und meinen Kommentar dazu

    
kludg 09.07.2010 02:18
quelle