Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Records unter 32 und 64Bit (https://www.delphipraxis.net/197680-records-unter-32-und-64bit.html)

EWeiss 27. Aug 2018 15:14

Records unter 32 und 64Bit
 
Ich stehe langsam wirklich auf Kriegsfuß mit 32 und 64Bit Anwendungen. :)
Anwendung kompiliert mit 32Bit alles fein.
Kurze und lange Pfade.

Anwendung kompiliert mit 64Bit.
1. gestartet aus einen langen Pfad. Alles fein (von der Performance mal abgesehen)
Code:
"C:\Program Files (x86)\Microsoft Visual Studio\VB98\Sourcemein\SKAero Projekte64\Sprite Control\Carousel\bin"
2. gestartet aus einem kurzen Pfad. Nichts mehr fein.
Code:
C:\Users\xxx\Desktop\Carousel\bin
Die Einträge im Record werden verändert.
Delphi-Quellcode:
  SpriteData = record
    ImageName: PWideChar;
    hBmp: HBitmap;
    ID: Integer;
    LabelID: Integer;
    xPos: Integer;
    yPos: Integer;
    Width: Integer;
    Height: Integer;
    Angle: single;
  end;
  TSpriteData = Array[1..10] of SpriteData;
Delphi-Quellcode:
var
  gSpriteData: TSpriteData;
Den Unterschied kann man in den angehängten Pics sehen.
Scheint so das 64Bit etwas gegen mich hat an vielen Ecken stoße ich auf seltsames verhalten.

gruss

Neutral General 27. Aug 2018 15:47

AW: Records unter 32 und 64Bit
 
PWideChar ist unter 64-Bit 8 Byte groß, statt 4. Dadurch sind alle weiteren Felder nach hinten verschoben im Speicher.

EWeiss 27. Aug 2018 15:51

AW: Records unter 32 und 64Bit
 
Um das ganze zu vereinfachen.. Quelltext im Anhang. (Setzt mindestens die CE zum kompilieren voraus)
Keine Exe im Archiv diese müsst ihr selbst kompilieren abhängig von der jeweiligen Plattform.
Die DLL von beiden Plattformen ist der gleiche Quelltext ohne jegliche Änderung.
Diese in das Bin Verzeichnis kopieren abhängig vom Kompilat das ihr erstellen wollt.

Es ist mir noch ein Problem aufgefallen.
Beim beenden der 32Bit Anwendung bekomme ich einen 216 Error bei 64Bit nicht!
Kein Problem muss das noch fixen wird wohl ein Handle sein das freigegeben wird und schon freigegeben wurde.
Nur seltsam das es hier bei 32Bit passiert und nicht mit 64..

Und so geht es weiter ;)

PS:
Damit könnt ihr auch die Probleme mit der CPU Auslastung testen die bei 64Bit 25% höher liegt als bei der 32Bit Plattform.

gruss

EWeiss 27. Aug 2018 15:53

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von Neutral General (Beitrag 1411746)
PWideChar ist unter 64-Bit 8 Byte groß, statt 4. Dadurch sind alle weiteren Felder nach hinten verschoben im Speicher.

Versteh danke..
Aber warum funktioniert es dann bei langen Pfaden? Da wird auch PWideChar verwendet. (Glück? )
Und es wird nicht alles verschoben wie du im shot sehen kannst nur die ersten beiden werden verändert.

gruss

Neutral General 27. Aug 2018 16:05

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von EWeiss (Beitrag 1411748)
Zitat:

Zitat von Neutral General (Beitrag 1411746)
PWideChar ist unter 64-Bit 8 Byte groß, statt 4. Dadurch sind alle weiteren Felder nach hinten verschoben im Speicher.

Versteh danke..
Aber warum funktioniert es dann bei langen Pfaden? Da wird auch PWideChar verwendet. (Glück? )
Und es wird nicht alles verschoben wie du im shot sehen kannst nur die ersten beiden werden verändert.

Mh stimmt.
Wie kommen denn die Daten in das Record bzw. Array?

EWeiss 27. Aug 2018 16:08

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von Neutral General (Beitrag 1411750)
Zitat:

Zitat von EWeiss (Beitrag 1411748)
Zitat:

Zitat von Neutral General (Beitrag 1411746)
PWideChar ist unter 64-Bit 8 Byte groß, statt 4. Dadurch sind alle weiteren Felder nach hinten verschoben im Speicher.

Versteh danke..
Aber warum funktioniert es dann bei langen Pfaden? Da wird auch PWideChar verwendet. (Glück? )
Und es wird nicht alles verschoben wie du im shot sehen kannst nur die ersten beiden werden verändert.

Mh stimmt.
Wie kommen denn die Daten in das Record bzw. Array?

Frage ich mich selbst..
Ich stoße wirklich auf viele dieser seltsamen verhalten in Verbindung mit 64Bit.
Ist auch glaube ich nicht nötig da ich damit keinen Record außerhalb der EXE ansprechen.

Habe es mit
Code:
{$ALIGN ON}
{$MINENUMSIZE 4}
versucht da ich dachte vielleicht liegt es hier dran.. aber nein keine Chance.

Wie sie da rein kommen bzw.. übergeben werden ist im Quelltext ersichtlich.

gruss

Neutral General 27. Aug 2018 16:14

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von EWeiss (Beitrag 1411751)
Wie sie da rein kommen bzw.. übergeben werden ist im Quelltext ersichtlich.

Ja das meinte ich.
Und das ist ein sehr wichtiger Punkt der besser in deinem Post enthalten wäre als *irgendwo* in deinem angehangenen Quelltext.
Es gibt wahrscheinlich nicht viele die sich nur deswegen deinen gesamten Code anschauen wollen. (Ich z.B. auch nicht)

EWeiss 27. Aug 2018 16:15

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von Neutral General (Beitrag 1411754)
Zitat:

Zitat von EWeiss (Beitrag 1411751)
Wie sie da rein kommen bzw.. übergeben werden ist im Quelltext ersichtlich.

Ja das meinte ich.
Und das ist ein sehr wichtiger Punkt der besser in deinem Post enthalten wäre als *irgendwo* in deinem angehangenen Quelltext.
Es gibt wahrscheinlich nicht viele die sich nur deswegen deinen gesamten Code anschauen wollen. (Ich z.B. auch nicht)

OK! Du hast recht :)
So werden sie übergeben.

Delphi-Quellcode:
 
var
  SpriteResPath: string;
//..
  SpriteResPath := ExtractFilePath(ParamStr(0)) + 'SpriteRes\';
 
  gSpriteData[1].ImageName := PWideChar(SpriteResPath + '3.png');
  gSpriteData[2].ImageName := PWideChar(SpriteResPath + '1.png');
  gSpriteData[3].ImageName := PWideChar(SpriteResPath + '2.png');
  gSpriteData[4].ImageName := PWideChar(SpriteResPath + '1.png');
  gSpriteData[5].ImageName := PWideChar(SpriteResPath + '2.png');
  gSpriteData[6].ImageName := PWideChar(SpriteResPath + '1.png');
  gSpriteData[7].ImageName := PWideChar(SpriteResPath + '2.png');
  gSpriteData[8].ImageName := PWideChar(SpriteResPath + '1.png');
  gSpriteData[9].ImageName := PWideChar(SpriteResPath + '2.png');
  gSpriteData[10].ImageName := PWideChar(SpriteResPath + '1.png');
gruss

Zacherl 27. Aug 2018 16:18

AW: Records unter 32 und 64Bit
 
Da liegt das Problem.
Delphi-Quellcode:
PWideChar
ist ein Zeiger und dein Konstrukt
Delphi-Quellcode:
SpriteResPath + 'irgendwas'
erzeugt eine temporäre RValue. Der Zeiger kann theoretisch in der nächsten Anweisung schon wieder ungültig sein. Dass das unter 32-Bit funktioniert, war reiner Zufall :-D

Also genauer gesagt: Durch deinen Cast nach
Delphi-Quellcode:
PWideChar
bringst du das interne Ref-Counting des Strings durcheinander. Besteht die Möglichkeit
Delphi-Quellcode:
.ImageName
einfach als
Delphi-Quellcode:
String
zu deklarieren? Das würde dein Problem lösen.

EWeiss 27. Aug 2018 16:18

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von Zacherl (Beitrag 1411756)
Da liegt das Problem.
Delphi-Quellcode:
PWideChar
ist ein Zeiger und dein Konstrukt
Delphi-Quellcode:
SpriteResPath + 'irgendwas'
erzeugt eine temporäre RValue. Der Zeiger kann theoretisch in der nächsten Anweisung schon wieder ungültig sein. Dass das unter 32-Bit funktioniert, war reiner Zufall :-D

Es funktioniert auch unter 64Bit aber nur mit langen Pfaden. :)

Zitat:

einfach als String zu deklarieren?
Jo das geht.. wäre kein Problem aber wie ich schon sagte mit langen Pfaden funktioniert es auch unter 64Bit.
Das sind so die dinge die ich nicht verstehe.

gruss

Zacherl 27. Aug 2018 16:22

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von EWeiss (Beitrag 1411758)
Jo das geht.. wäre kein Problem aber wie ich schon sagte mit langen Pfaden funktioniert es auch unter 64Bit.

Kann schon sein, ist aber ebenfalls "Zufall", dass das funktioniert. Mit
Delphi-Quellcode:
String
deklariert bist du immer auf der sicheren Seite :thumb:

Uwe Raabe 27. Aug 2018 16:25

AW: Records unter 32 und 64Bit
 
Hat vermutlich gar nichts mit den Strings/PWideChars zu tun, aber

Delphi-Quellcode:
var
  ...
  DC: Cardinal;

...

DC := GetDC(MainHandle);
könnte unter 64-Bit einen Überlauf erzeugen, da ein HDC dort nicht mehr in einen Cardinal passt.

EWeiss 27. Aug 2018 16:28

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von Zacherl (Beitrag 1411759)
Zitat:

Zitat von EWeiss (Beitrag 1411758)
Jo das geht.. wäre kein Problem aber wie ich schon sagte mit langen Pfaden funktioniert es auch unter 64Bit.

Kann schon sein, ist aber ebenfalls "Zufall", dass das funktioniert. Mit
Delphi-Quellcode:
String
deklariert bist du immer auf der sicheren Seite :thumb:

Ich sollte mal Lotto spielen bei den ganzen Zufällen die ich habe und die zumeist funktionieren sollte ich schon bald Millionär sein ;)

So geht's. Mit String.
Muss da wohl insbesondere bei 64Bit in der Zukunft sehr drauf achten der Kompatibilität wegen.

Der sinn des ganzen warum ich hier einen PWideChar definiert habe ist dieser damit ich ihn nachher nicht nochmal casten muss bei der Übergabe an die Library.
Das muss ich hier jetzt tun.
Delphi-Quellcode:
gSpriteData[K].hBmp := gSprCtrl.GI_CreateMirrorBitmapFromFile
  (PWideChar(gSpriteData[K].ImageName), imgW, imgH);

Also ich habe mir schon was dabei gedacht. ;)

gruss

EWeiss 27. Aug 2018 16:31

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1411760)
Hat vermutlich gar nichts mit den Strings/PWideChars zu tun, aber

Delphi-Quellcode:
var
  ...
  DC: Cardinal;

...

DC := GetDC(MainHandle);
könnte unter 64-Bit einen Überlauf erzeugen, da ein HDC dort nicht mehr in einen Cardinal passt.

Ja das ist definitiv falsch (keine Ahnung was mich da wieder mal geritten hat) muss HDC sein.
Werde es beheben und berichten.

Danke.

PS:
Liegt am string..
Das DC ist nur für den Blink Button.

Diese Änderung wirkt sich auch nicht auf die CPU Auslastung aus die bleibt bei 64Bit 25%
Dort habe ich jetzt schon versucht MMTimer (Hochauflösender Timer vom MMSystem inkl. QueryPerformanceFrequency Callback usw.
Ein Sleep(0) oder Sleep(1) bringt auch nichts.
Den Timer auf 25ms zu setzen bremst das gesamte zeichnen aus.

Danke für eure Hilfe funktioniert jetzt so.

gruss

Dennis07 29. Aug 2018 18:43

AW: Records unter 32 und 64Bit
 
Kleine Anmerking, anstatt an dem ALIGN rumzuspielen, kann man auch einfach einen
Delphi-Quellcode:
packed record
bzw. ein
Delphi-Quellcode:
packed array
draus machen.

Zacherl 29. Aug 2018 21:31

AW: Records unter 32 und 64Bit
 
Zitat:

Zitat von Dennis07 (Beitrag 1411949)
Kleine Anmerking, anstatt an dem ALIGN rumzuspielen, kann man auch einfach einen
Delphi-Quellcode:
packed record
bzw. ein
Delphi-Quellcode:
packed array
draus machen.

Nöö, es geht ja nichtmal tatsächlich um Records, sondern um Enums. Und einfach den Record
Delphi-Quellcode:
packed
zu machen bringt gar nichts, wenn auf API-Seite (z.B. C Dll) der Record korrekt aligned ist. Das Alignment sollten die meisten Compiler sowieso gleich handhaben. Problematisch ist halt bei so Dingen, dass Delphi die Enums immer versucht in den kleinstmöglichen Typ zu packen (
Delphi-Quellcode:
{$Z1}
), während die Min-Enum-Size unter C/C++ der Größe eines
Delphi-Quellcode:
int
s entspricht, also unter Windows dann 4-Byte groß ist. Deshalb muss man Delphi an dieser Stelle mit
Delphi-Quellcode:
{$Z4}
beibringen dies für die betroffenden Enums ebenfalls so zu machen.

Und nebenbei ist
Delphi-Quellcode:
packed
äquivalent zu
Delphi-Quellcode:
{$A1}
, macht also keinen großen Unterschied was man verwendet - wobei ich persönlich das
Delphi-Quellcode:
packed
auch vorziehen würde.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:42 Uhr.

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