Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Fehler in Record-Ausrichtung bei Übergabe an Visual C DLL (https://www.delphipraxis.net/1917-fehler-record-ausrichtung-bei-uebergabe-visual-c-dll.html)

oki 30. Dez 2002 16:09


Fehler in Record-Ausrichtung bei Übergabe an Visual C DLL
 
Hallo,

ich hab hier ein ganz blödes Problem. Für ein aktuelles Projekt rufe ich Methoden aus einer Dll mit Parameterübergabe mittels Zeiger auf Strukturen auf. Hierbei bekomme ich sporadisch Lesefehler auf Adressen aus der DLL.
Nach einem Gespräch mit dem Ersteller der DLL habe ich folgenden Tip überprüft.
Die DLL ist in Visual C geschrieben und erwartet eine 8 Byte Ausrichtung für Structuren (Records) im Speicher.
Nun richtet Delphi in der Regel an 32 Bit (4 Byte) Grenzen aus.
Somit habe ich den notwendigen Speicher mit GlobalAlloc reserviert (hier soll nach SDK auf jeden Fall an 8 Byte Grenzen ausgerichtet werden).
Jetzt mußte ich feststellen, dass meine Recordausrichtung zwar auf 32 Bit erfolgt, aber der Lesefehler trotzdem bleibt. Nach mühsammen debuggen mußte ich feststellen, dass mit dem Methodenaufruf aus der DLL die Structure an eine Speicherstelle kopiert wird die nicht an 8 Byte Grenzen ausgerichtet ist.

Jetzt kommt der absolute Spaß!!!!!!!!!

Füge ich in meinem Quellcode zusätzliche Codezeilen ein (müssen nichts mit benannter Structure zu tun haben) klappt auch mall alles prima.

Was ist da los?

Wie kann ich meinen Compiler überreden Speicher automatisch an 8 Byte Grenzen auszurichten? Ich bin hier aktuell etwas hilflos und finde zu diesem Thema keine vernünftigen Info's.

Ach ja, ich benutze Delphi 5 Enterprise.

Gruß oki. :cry:

sakura 30. Dez 2002 16:15

Einfach an den Anfang der Units, welche es betrifft
Code:
{$ALIGN 8}
einfügen. Wenn der Compiler das nicht schluckt, dann hast Du leider Pech. Der Schalter ist in D7 beschrieben, ob D5 den schon hat, ich glaube leider nicht.

Brüggendiek 30. Dez 2002 16:23

Hallo!

Zitat:

Zitat von sakura
Der Schalter ist in D7 beschrieben, ob D5 den schon hat, ich glaube leider nicht.

D5 Standard kennt nur {$ALIGN ON} / {$A+}: Record-Werte ausrichten bzw. {$ALIGN OFF} / {$A+}: Record-Werte nicht ausrichten, also alle RECORDs als PACKED speichern. Voreinstellung: {$A+}.

Leider!

Gruß

Dietmar Brüggendiek

Christian Seehase 30. Dez 2002 18:25

Moin Oki,

also dass man auf Grund eines falschen Alignments CPU Strafzyklen erhält hab' ich ja schon gehört, aber das die Daten auf eine bestimmte Adresse ausgerichtet sein müssen, damit der Zugriff überhaupt erfolgen kann ist mir neu.

Diese Ausrichtung soll ja eigentlich nur dafür sorgen, dass die CPU das Programm schneller abarbeiten kann, wenn die Daten an einer Grenze liegen die der generischen Adressbus Breite der CPU entspricht, was bei einem 8 Byte Alignment ja eindeutig auf eine 64 Bit CPU hindeutet.

Ausser die DLL geht mit übergebenen Pointern sehr eigenwillig um ( ;-)) dürfte das nicht zu einem Fehler führen, sondern schlimmstenfalls zu einer langsameren Abarbeitung des Programmes.

Kann es sein, dass der von Dir benutzte Record als record und nicht als packed record deklariert ist?

oki 30. Dez 2002 18:51

Erst mal herzlichen Dank für die schnellen Antworten.

Leider stimmt es, dass D5 die Direktive ALIGN 8 nicht kennt. Ich werde es trotzdem einfach mal probieren.

Leider ist es wirklich so, dass die Daten an einer 8 Byte Ausrichtung erwartet werden. Ich habe es im Debuger geprüft. Bei einem Versatz der Structure um 4 Byte im Speicher wird beim kopieren das erste DWord einfach ignoriert. Mein Kontakt hat mir außerdem berichtet, dass Visual C mit Sicht auf 64 Bit-Processoren grundsätzlich eine 64 Bit-Ausrichtung erwartet.
Ob das alles so korrekt ist weiß ich nicht. Vielleicht ist die Speicherbearbeitung auch wieder einmal so'n komisches C-Programmiererteil.
Mein Problem ist aber nachweisbar das beschriebene.

Vieleicht hat ja noch einer 'ne Idee.

Bis dann Olaf

Christian Seehase 30. Dez 2002 23:48

Moin Olaf,

Zitat:

dass Visual C mit Sicht auf 64 Bit-Processoren grundsätzlich eine 64 Bit-Ausrichtung erwartet.
Also ich kann mir vorstellen, dass das als Defaulteinstellung gilt, aber nicht, dass es unabänderlich ist. (hab' leider gerade keine VC zur Hand)

So wie es aussieht scheint's da wohl nur zwei Lösungsansätze zu geben:
  1. Du steigst auf D7 um damit Du die DLL sicher benutzen kannst. (wenn's denn mit Align 8 wie gewünscht geht)
  2. Die DLL wird mit 32 Bit Alignment neu kompiliert.

oki 31. Dez 2002 14:33

Hallo Christian,

Dank für die Antwort. Ich werd mal versuchen den C-Programmierer zu beschwatzen mir ein neues Compiling zu schicken bevor ich Geld für D7 in die Hand nehme.

Gruß Olaf

OregonGhost 31. Dez 2002 15:55

Kannst du nicht einfach die struct, Verzeihung, den record packed machen und die zur 8-Byte-Ausrichtung fehlenden Bytes einfach als leere Bytes hinzufügen? Wenn ich das Problem richtig verstanden habe :roll: , müsste das doch so gehen...

Leider kann man zumindest in VC6.01 SP4 nur 1 bis 16 Byte als struct-Elementausrichtung einstellen...

Christian Seehase 31. Dez 2002 17:45

Moin Oregon Ghost,

wenn eine Ausrichtung von 1 bis 16 einstellbar ist, ginge doch auch 4 oder nicht?

oki 1. Jan 2003 17:36

Hallo ihr alle zusammen.

Für mein erstes Problem habe ich eine Lösung gefunden (der erste Eindruck ist jedenfalls so). Ich habe für den Record einfach ausreichend Speicher mittels GlobalAlloc auf einen Zeiger vom Typ PChar reserviert. Laut SDK soll GlobalAlloc Adressen in einer 8 Byte-Ausrichtung reservieren. Die entsprechenden Einträge habe ich dann mittels move-Befehl an die entsprechende Stelle Zeiger[x] kopiert.
Das sah alles erstmal richtig gut aus.

Ergebnis der Aktion -----------> Fehlermeldung aus der DLL!!!

Jetzt habe ich mich mühsam mittels CPU-Debugger durch den Code gequält und folgendes festgestellt.
Mein Record wird ordnungsgemäß angelegt und an die DLL-Methode übergeben. Die DLL-Methode legt einen eigenen Speicherbereich an der aber jetzt nicht an einer 8 Byte Grenze ausgerichtet ist!!!! :witch: Jetzt wird mein Speicherinhalt mit einer Ausrichtung an einer 8 Byte-Adresse in diesen Speicher kopiert. Somit entsteht ein Versatz von 4 Byte.

Jetzt kommt meine doofe Frage:

Das passiert doch alles in der DLL. Was habe ich damit zu tun?
Muscht der Delphi-Compiler irgentwo rum, dass der an die Basisadresse geladene DLL-Code Mist baut?
Ich weiß, dass sich das jetzt alles ganz schön blöd anhört, aber ich habe C-Beispielcode bekommen, bei dem alles super mit der DLL klappt.

Vielleicht hat ja noch einer eine Idee.

Übrigens vielen Dank für die Tips mit dem Auffüllen und den packed record's. Hab ich leider vorher schon probiert (sicher erfolglos weil das Problem woanders steckt).

Gruß Olaf


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:37 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz