Page 1 of 2 1 2 LastLast
Results 1 to 15 of 28

Thread: Fout in Win32 compiler??

  1. #1
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    151

    Fout in Win32 compiler??

    Ik heb een stuk code (even versimpeld) dat altijd goed werkte.

    Code:
      TTestThread = class(TThread)
      private
        Data: record
          Test,// : Extended;
          Test1: Extended;
        end;
        procedure SetTest(AValue: Extended);
        procedure SetTest1(AValue: Extended);
      protected
        procedure Execute; override;
      public
        property Test: Extended read Data.Test write SetTest;
        property Test1: Extended read Data.Test1 write SetTest1;
      end;
    Maar sinds de overgang van XE8 naar DX10 gaat er iets mis als ik bovenstaande in Win32 compileer.
    via de onderstaande button click test ik het object:

    Code:
    procedure TTestForm.TestBtnClick(Sender: TObject);
    var
      tt  : TTestThread;
      t,
      t1  : Extended;
    begin
      tt := TTestThread.Create(true);
      with tt do
      try
        Test := 12.3;
        Test1 := 45.6;
        try
          t := Test;
          t1 := Test1;
          Self.Caption := Format('Test=%.1f | Test1=%.1f', [t, t1]);
        except
          on E:Exception do Application.MessageBox(PChar(E.Message), 'Foutje')
        end;
      finally
        Free
      end
    end;
    Als ik via de properties Test en Test1 schrijf en daarna de waardes teruglees in t en t1 dan komt de t1 niet overeen (3,72036854775808e+2959 ipv 45.6)
    Als ik echter een break plaats en via de debugger de waardes in tt.Data bekijk, dan staan daar wel de goede waardes?!?

    Het onderstaande heb ik al geprobeerd en getest.

    Als ik in Win64 compileer gaat het goed.
    Als ik Double ipv Extended gebruik gaat het goed.
    Als ik Test direct als Extended definieer gaat het goed.

    Daarnaast gaat het ook goed
    als ik een getter én een setter gebruik
    of als ik géén getter en géén setter gebruik.

    Dus ik kan er omheen werken, maar ben wel benieuwd waardoor dit optreedt?
    En het feit dat Win32 tov Win64 compileren (voor het eerst) een probleem geeft in "simpele" code, doet mij diep fronsen.

    Moeten Embarcadero wakker geschopt worden of zie ik iets over het hoofd?

  2. #2
    Ik vraag me vooral af wat er gebeurt in de setters en wat er gebeurt in Execute. Je bent niet voor niets met een thread bezig, neem ik aan, maar al het magische gedrag dat daaruit kan voortkomen is niet zichtbaar in je vraag.
    1+1=b

  3. #3
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Dingen die direct opvallen:

    1. Je creert de thread suspended, maar je start hem niet.
    2. Je freed de thread zonder controlleren of deze daadwerkelijk afgelopen is (terminated, waitfor?)
    3. Je leest waardes van de thread zonder enige vorm van synchonizatie, een zeer korte tijd nadat je ze schreef, een tijd die gemeten wordt in processor cycli (dus nanoseconden of zo).
    4. Er is niet genoeg code om het geheel te kunnen volgen of testen.


    En de laatste is ook de reden waarom mijn (en ik neem aan Goleztrol') antwoord zo summier zijn. Summier in, summier eruit, zo te zeggen. Probeer bij uitbreiden ook een beetje uit te leggen wat je wilt bereiken.

    Ik zou Embarcadero nog maar ff met rust laten, dit lijkt me niet iets om je kostbare contactmomenten van de subscription aan te verknoeien.

  4. #4
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    151
    De Execute is een lege procedure in de test.
    De Setters zijn gewoon waarde toekenningen:
    Code:
    procedure TTestThread.Execute;
    begin
    // Free on terminate
    end;
    
    procedure TTestThread.SetTest(AValue: Extended);
    begin
      Data.Test := AValue;
    end;
    
    procedure TTestThread.SetTest1(AValue: Extended);
    begin
      Data.Test1 := AValue;
    end;
    In het echie doen de Execute en Setters natuurlijk veel meer.

    Ik heb net XE8 weer geinstalleerd, en die doet het op zowel Win32 als Win64 wel goed

  5. #5
    Dit werkt bij mij ook prima.

    Lege form met knop en deze code erin geplakt.
    Delphi 10.1 Berlin (win32 en win64).

    Delphi Code:
    1. type
    2.   TTestClass = class(TThread)
    3.   private
    4.     Data: record
    5.       Test,// : Extended;
    6.       Test1: Extended;
    7.     end;
    8.     procedure SetTest(AValue: Extended);
    9.     procedure SetTest1(AValue: Extended);
    10.   protected
    11.     procedure Execute; override;
    12.   public
    13.     property Test: Extended read Data.Test write SetTest;
    14.     property Test1: Extended read Data.Test1 write SetTest1;
    15.   end;
    16.  
    17. procedure TTestClass.Execute;
    18. begin
    19.   inherited;
    20.  
    21. end;
    22.  
    23. procedure TTestClass.SetTest(AValue: Extended);
    24. begin
    25.   Data.Test := AValue;
    26. end;
    27.  
    28. procedure TTestClass.SetTest1(AValue: Extended);
    29. begin
    30.   Data.Test1 := AValue;
    31. end;
    32.  
    33. procedure TForm1.Button1Click(Sender: TObject);
    34. var
    35.   tt  : TTestClass;
    36.   t, t1  : Extended;
    37. begin
    38.   tt := TTestClass.Create(true);
    39.   with tt do
    40.   try
    41.     Test := 12.3;
    42.     Test1 := 45.6;
    43.     try
    44.       t := Test;
    45.       t1 := Test1;
    46.       Self.Caption := Format('Test=%.1f | Test1=%.1f', [t, t1]);
    47.     except
    48.       on E:Exception do Application.MessageBox(PChar(E.Message), 'Foutje')
    49.     end;
    50.   finally
    51.     Free
    52.   end
    53. end;

  6. #6
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    151
    Waar ik naar toe wil is dat als ik een waarde schrijf, ik die waarde ook weer teruglees.

    Ik heb hier Delphi 10.2 Update 3, Tokyo

    Op een andere PC heb ik hetzelfde probleem. Win32 fout Win64 gaat goed.
    Last edited by Knollie; 06-Sep-18 at 16:24.

  7. #7
    Ook die versie gaat bij mij prima.

  8. #8
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Na ja, dan draait de thread niet eens. Het is dan vooral een heel ingewikkelde manier om variabelen de declareren.

    Test eens met rvk's voorbeeld, ipv je eigen, misschien is er een detail gemist.

  9. #9
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    151
    In het project dat al sinds 2015 werkt, ging het tot nu toe altijd goed zowel Win32 als Win64.

    Als ik van de TThread een TObject maak (dus geen execute) blijft de fout optreden bij het schrijven en lezen van Test1.
    Alsof de interne verwerking in de Data record niet goed werkt.

    Ben nu een verse 10.2.3 aan het installeren op een VM zonder extra units. Kijken of die wel wil werken.

  10. #10
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Heb je nu met rvk's project getest? Als dat goed gaat, is het mogelijk iets van wijzigen van packing instellingen?

  11. #11
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    151
    ik heb rvk's code getest,

    maar op alle drie de machines met Delphi 10 gaat het mis in Win32.
    Op de machine met XE8 gaat wel goed.

    Ik zal de package instellingen morgen eens vergelijken.
    En ook een VM met een andere Windows 10 versie maken.

  12. #12
    Senior Member Wok's Avatar
    Join Date
    Dec 2002
    Location
    Alkmaar
    Posts
    2,085
    Click image for larger version. 

Name:	fout.PNG 
Views:	101 
Size:	4.2 KB 
ID:	7792

    Ik was gewoon nieuwsgierig.

    Delphi 10 Berlin En Tokyo zowel Win32 als Win64 werken gewoon.
    Ik denk dat je het ergens anders moet gaan zoeken.
    Uithuilen en opnieuw beginnen. stap voor stap

    gr.Peter
    10.4.2, Delphi2010, of Lazarus 2.2.0

  13. #13
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Schrijf sizeof(Data) naar console, gui of outputdebugstring.

  14. #14
    Senior Member
    Join Date
    Aug 2004
    Location
    Rotterdam
    Posts
    151
    Bedankt voor jullie input tot zover. Ik ben nog even verder gaan testen en ben de pointers gaan vergelijken.

    Een Extended is 10 bytes, en mijn Record Field Alignment staat op Quad Word = 8 bytes (is standaard).
    De pointers in de data record lopen op met 16 want er worden 2 x 8 bytes per extended gebruikt.
    Code:
        Data: record
          Test,           //  $0000A010
          Test1: Extended;//  $0000A020
        end;
        property Test: Extended read Data.Test;  //   $0000A010
        property Test1: Extended read Data.Test1; //   $0000A01A
    De pointer van de Property Test1 read is hier echter maar 10 bytes hoger, waardoor het tweede element dus niet van de juiste plek wordt gelezen.

    Verander ik de record definitie nu in:
    Code:
        Data: record
          Test: Extended;  //  $0000A010
          Test1: Extended; //  $0000A020
        end;
        property Test: Extended read Data.Test;  //   $0000A010
        property Test1: Extended read Data.Test1; //   $0000A020
    Dan is de pointer van de Property Test1 read wel 16 bytes hoger, waardoor het tweede element dus wel van de juiste plek wordt gelezen.

    Bij beide Date definities krijg ik een SizeOf(Data) = 32 bytes.

    Waarom dit in Win64 goed gaat is omdat Delphi in Win64 een Extendend als een Double ziet (8 bytes die precies op Quad Word alignment vallen)
    Bij recorder alignment None, Byte & Word gaat het ook goed op Win32
    Bij Double Word alignment wordt er in de data record een sprong van 12 bytes gemaakt en treedt hetzelfde probleem op.

    Vraagje aan rvk: Zou jij kunnen kijken met welke record alignment jij de beide tests hebt gedaan?
    Last edited by Knollie; 07-Sep-18 at 13:18.

  15. #15
    Quote Originally Posted by Knollie View Post
    Vraagje aan rvk: Zou jij kunnen kijken met welke record alignment jij de beide tests hebt gedaan?
    Ik heb gewoon een nieuw project aangemaakt dus die record alignment stond op de standaard (Quad word).

    PS. Nu heb je bij beide "read Data.Test" staan maar ik neem aan dat dat komt door een tikfout aan jou kant bij het maken van de post.

    Tevens vind ik het raar dat dit bij ons wel goed gaat op Win32 en bij jou fout.

    Bij mij is Addr(Test) $308F818 en Addr(Test2) $308F828 als ik een breakpunt in SetTest1 zet.
    Dat gaat dan ook om de property (want zet ik er een Test_dummy tussen dan zit er ook #20 verschil tussen).

    Maak van "property Test" eens "property aTest" (en idem bij Test1).

Page 1 of 2 1 2 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •