Autor Téma: Pointer ve vlákně  (Přečteno 415 krát)

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 108
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Pointer ve vlákně
« kdy: 08-09-2021, 12:18:09 »
Ahoj, zjevně něco zapisuji špatně, ale nedokážu přijít na to, co konkrétně.
Můj záměr. Mám vlákno, které v sobě má pole bajtů a třídu vykonávající nějakou činnost. Ukazatel na toto pole předá třídě, ta si obsah pole přečte a něco udělá.
Pointer se normálně předává, ale když chci z toho pole něco přečíst, tak mi to vrátí hlášku "Project raised Exception class $C0000005 with message access violation at ... read of address ADRESA". Zajímavé je to, že ADRESA odpovídá obsahu toho pole..

Kód mám přibližně tento:
Kód: Delphi [Vybrat]
  1. unit Unit1;
  2.  
  3. interface
  4. type
  5.     TCommandList = Array Of Byte;
  6.     PCommandList = ^TCommandList;
  7.  
  8.     TCommand = Class
  9.                 Procedure ExecuteBody(VCommandList : PCommandList;Var VPozice : Byte);
  10.                End;
  11.  
  12.  
  13.     TCommandRoutine = Class
  14.                        private
  15.                         pObsahByte      : PCommandList;
  16.                         pPozice         : Byte;
  17.                         pCommand        : TCommand;
  18.                       public
  19.                        Constructor Create(VSeznam : PCommandList);
  20.  
  21.                        Procedure Execute;virtual;
  22.                      End;
  23.  
  24.     TAPrikazy1 = Array [0..1] Of Byte;
  25.  
  26.     TRun = Class(TThread)
  27.             protected
  28.              pPrikazy : TCommandRoutine;
  29.             public
  30.              cPrikazy : TAPrikazy1;
  31.  
  32.             Procedure Napln;
  33.             Procedure Execute;override;
  34.            End;
  35. implementation
  36.  
  37. { TCommand }
  38.  
  39. procedure TCommand.ExecuteBody(VCommandList: PCommandList; var VPozice: Byte);
  40. Var
  41.    __B : Byte;
  42. begin
  43.  __B:=VCommandList^[VPozice]; //Tady to vyhodí exception, že chybně čte z adresy $0081, když to nastavení pole změním třeba na $88,$55 tak to v chybě napíše adresu $5588
  44. end;
  45.  
  46. { TCommandRoutine }
  47.  
  48. constructor TCommandRoutine.Create(VSeznam: PCommandList);
  49. begin
  50.  inherited;
  51.  pObsahByte:=VSeznam;
  52.  pCommand:=TCommnad.Create;
  53.  pPozice:=0;
  54. end;
  55.  
  56. procedure TCommandRoutine.Execute;
  57. begin
  58.  pCommand.ExecuteBody(pObsahByte,pPozice);
  59. end;
  60.  
  61. { TRun }
  62.  
  63. procedure TRun.Execute;
  64. begin
  65.  pPrikazy.Execute;
  66. end;
  67.  
  68. procedure TRun.Napln;
  69. begin
  70.  cPrikazy[0]:=$81;
  71.  cPrikazy[1]:=$0;
  72.  pPrikazy:=TSeznamPrikazu.Create(@cPrikazy); //Zajímavé je, že když si tady dám Watch @cPrikazy, tak mi to nevrátí adresu, ale obsah pole ($81,0), na zásobníku je ovšem uložena adresa toho pole.
  73. end;
  74.  
  75. end.
  76.  
  77.  

Nevíte, co mám špatně?

Ještě doplním Delphi 10.4
« Poslední změna: 08-09-2021, 12:24:22 od PetrB0 »

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 108
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Re:Pointer ve vlákně
« Odpověď #1 kdy: 09-09-2021, 00:22:04 »
Tak už to funguje dle předpokladu, ale pořád tomu nerozumím.
Trochu jsem upravil definici TRun
Kód: Delphi [Vybrat]
  1.  TRun = Class(TThread)
  2.             protected
  3.              pPrikazy : TCommandRoutine;
  4.             public
  5.              cPrikazy : TAPrikazy;
  6.  
  7.             Procedure Napln;
  8.             Procedure Execute;override;
  9.            End;
  10.  
  11. procedure TRun.Napln;
  12. Var
  13.      p : PCommandList;
  14. begin
  15.  SetLength(cPrikazy,2);
  16.  cPrikazy[0]:=$81;
  17.  cPrikazy[1]:=$0;
  18.  p:=@cPrikazy;
  19.  pPrikazy:=TSeznamPrikazu.Create(p); //Teď už p ve watch ukazuje adresu pole a při rozbalení jeho obsah. Problémová rutina už funguje normálně.
  20. end;
  21.  
  22.  

Myslíte, že jsem měl někde chybu?
Jediné, co mne napadá je, že Array of Byte je něco jiného než Array[0..1] Of Byte, ale předpokládal jsem že to můžu v klidu přetypovat (myslím, že dříve jsem to takto běžně dělal).

Aha, tak už asi vím. @cPrikazy ukazuje na ukazatel, kde je uloženo @cPrikazy[0]
Kdežto když mám P:Array[0..1] Of byte, tak  @P=@P[0]. To bude to jádro pudla...

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3286
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Pointer ve vlákně
« Odpověď #2 kdy: 09-09-2021, 08:06:43 »
Array of Byte je něco jiného než Array[0..1] Of Byte
Hmm, zil jsem v domneni, ze jsem ti to napsal, ale ne :-[

Mrkni na staticke vs. dynamicke pole https://docwiki.embarcadero.com/RADStudio/Sydney/en/Internal_Data_Formats_(Delphi)

Offline PetrB0

  • Plnoletý
  • ***
  • Příspěvků: 108
  • Karma: 1
    • Verze Delphi: Delphi XE2, Delphi 10.2 Tokyo, Delphi 10.41
Re:Pointer ve vlákně
« Odpověď #3 kdy: 09-09-2021, 23:10:46 »
Díky, to je v pohodě. Alespoň mne to donutilo trochu více přemýšlet. Mě mátlo to, že historicky mi to fungovalo, ale rozdíl byl v tom, že jsem používal statická pole. Dynamická hodně výjimečně, takže se mi to napoprvé (ani napodruhé, nebo napočtvrté) nespojilo ;-)