Toon posts:

[DELPHI] [TLIST] @ probleem ??

Pagina: 1
Acties:

Verwijderd

Topicstarter
Nou daar ben ik dan weer... hopelijk ditmaal een duidelijke fout omschrijving... maar tevens zal ik de code toevoegen zodat je het zelf kan zien ....

De bedoeling is dat ik een string gevuld met -> alleen <- maar 0 of 1-en inlees, om hier vervolgens een array of array of integer van 5x5 van te maken... daarna maak ik er een 3d array van die 5x5x8 is... heel vaag allemaal maar ik heb zo mijn redenen. Maar we zijn nog niet klaar ... deze 3Darray's zet ik vervolgens in een - function TForm1.Inladen : TList; - dan krijg ik een keurig lijst met 1 tjes en 0-etjes..

MAAAAAAR: wanneer ik buiten de functie de verzameling oproep om heb vervolgens weer op te zetten krijg ik hier en daar verkeerde waardes tussen door varierend van 3..6 tot 160000 ofzo ..

Heeft iemand enig idee ??

[ps .. de code is zo ver mogelijk gestript om er beetje inzicht in te krijgen... dus als sommige dingen nu niet meer logisch zijn... dat heeft een reden ]


Het probleem is: als ik de TList vervolgens weer omzet naar 5x5 array en deze weer uitlees heb ik 2 situaties:
- als ik het in LADEN() doe

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
unit HappyCube;

interface

uses
  SysUtils,
  Classes,
  Graphics,
  Controls,
  Forms,
  StdCtrls,
  contnrs ;

type
  TVerzameling = array[0..7, 0..4, 0..4] of Integer;
  TBlokje = array[0..4, 0..4] of Integer;
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure ShowInList(myList : TList);

    function StringToCube(CubesString : String) : TBlokje;
    function Inladen : TList;
    function VulVerzamelingList(myBlok : TBlokje): TVerzameling;

  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  List : TList;

implementation

{$R *.DFM}

function TForm1.VulVerzamelingList(myBlok: TBlokje): TVerzameling;
var
  TempVerzameling : TVerzameling;
  Stuknr,row,col : Integer;
begin
  for Stuknr := 0 to 7 do
    for row := 0 to 4 do
      for col := 0 to 4 do
        TempVerzameling[Stuknr][row][col] := myBlok[row][col];

  Result := TempVerzameling
end;

procedure TForm1.ShowInList(myList: TList);
var
  p : ^TVerzameling;
  temp : TVerzameling;
  a,b,c,l : Integer;
begin
  for l := 0 to myList.Count - 1 do
  begin
  p := myList.Items[l];
  temp := p^;
    for a := 0 to 7 do
      for b := 0 to 4 do
        for c := 0 to 4 do
         ListBox1.Items.Add('l,a,b,c = ' + IntToStr(l) + ',' + IntToStr(a) + ',' + IntToStr(b) + ',' + IntToStr(c) + ' ---> ' + IntToStr(temp[a,b,c]));
  end;
end;

function TForm1.Inladen : TList;
var
  BlokA,BlokB,BlokC,BlokD,BlokE,BlokF : TBlokje;
  tempVerz : TVerzameling;
  VerzamelingenList : TList;
begin

  BlokA := StringToCube('0101001111111100111111010'); // stuk 1
  BlokB := StringToCube('0010111111011101111111010'); // stuk 2
  BlokC := StringToCube('0010001110111110111000100'); // stuk 3
  BlokD := StringToCube('0010001111111100111111011'); // stuk 4
  BlokE := StringToCube('0010011111011101111100101'); // stuk 5
  BlokF := StringToCube('0101001110111110111011011'); // stuk 6

  VerzamelingenList := TList.Create;

  tempVerz := VulVerzamelingList(BlokA);
  VerzamelingenList.Add(@tempVerz);
  tempVerz := VulVerzamelingList(BlokB);
  VerzamelingenList.Add(@tempVerz);
  tempVerz := VulVerzamelingList(BlokC);
  VerzamelingenList.Add(@tempVerz);
  tempVerz := VulVerzamelingList(BlokD);
  VerzamelingenList.Add(@tempVerz);
  tempVerz := VulVerzamelingList(BlokE);
  VerzamelingenList.Add(@tempVerz);
  tempVerz := VulVerzamelingList(BlokF);
  VerzamelingenList.Add(@tempVerz);

Result := VerzamelingenList;
end;

function TForm1.StringToCube(CubesString: String): TBlokje;
var
  row,col,i : integer;
  tempBlokje : TBlokje;
begin
  i := 1;
  for row := 0 to 4 do
    for col := 0 to 4 do
    begin
      tempBlokje[row,col] := StrToInt(Copy(CubesString, i, 1));
      Inc(i);
    end;

  Result := tempBlokje;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowInList(Inladen);
end;

end.

  • MaxxRide
  • Registratie: April 2000
  • Laatst online: 09-01 10:13

MaxxRide

Surf's up

Denk dat je even goed moet kijken naar je pointers. Ik zie het probleem zo ook niet, maar dat zijn toch vaak wel erg tricky dingen, die pointer!

Ik denk dat je even goed moet kijken naar tempVerz pointer, dat is namelijk een pointer die de hele tijd naar hetzelfde stukje geheuge wijst, en dat zit je de hele tijd te overschrijven. Dit kun je allemaal het beste uitzoeken middel DEBUGGEN en er rustig doorheen stappen. Zo op 'papier' is het veel te moeilijk om de fout te vinden!

If you are not wiping out you are nog pushing enough...


Verwijderd

Topicstarter
Nou ik haal hem door de Debugger.. en zo uit het niets ( voor mij dan ) krijgt een waarde ipv 0 / 1 de waarde 123428 ofzo :S ....
Moet ik soms de pointers na gebruik gelijk nil-en ??

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Je idee is aardig, maar je maakt nog niet genoeg gebruik van het geheugen.

Wat je doet is in VulVerzamelingList een locale TVerzameling retouneren. Dat geugen is wel geldig binnen die functie en op het moment van retouneren, maar zodra je uit VulVerzamelingList gaat wordt dat geheugen weer vrijgemaakt. Het is best mogelijk dat de juiste waardes er nog toevallig een tijdje in blijven staan, maar voor je het weet worden ze overschreven met andere.

Maak in Inladen met new/alloc elke keer een nieuwe TVerzameling en geef die door aan VulVerzamelingList. Of laad VulVerzamelingList ze elke keer opnieuw creeeren.

Als je iets Creeerd met Create/New/Alloc moet je ook niet vergeten hetzelf ook weer vrij te maken, anders heb je een memory leak.

We adore chaos because we like to restore order - M.C. Escher


  • MaxxRide
  • Registratie: April 2000
  • Laatst online: 09-01 10:13

MaxxRide

Surf's up

Wat je ook kunt doen, is i.p.v. iets te retourneren een var parameter meegeven. Dit vind ik zelf mooier, je creeert dan namelijk je array op het punt waar je deze ook zult moeten free-en...

Ik weet niet wat een result doet of deze de waarde copieert (wat mij wel lijkt omdat je met arrays werkt) of dat ie een pointer meegeeft. Dit naar aanleiding van het bericht van LordLarry.

If you are not wiping out you are nog pushing enough...


Verwijderd

Topicstarter
en als ik de list nu public maak ?? worden we daar beter van ??

Verwijderd

Topicstarter
:'( ... ik maak nu een nieuwe Tlist aan ... en gebruik deze vervolgens.. maareh .. probleem is er alleen maar erger op geworden.. wat doe ik fout ???

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
procedure TForm1.Button1Click(Sender: TObject);
var
  myVerzList : TList;
begin
  myVerzList := TList.Create;
  try
    myVerzList := InLaden;
    ShowInList(myVerzList);
    InLaden;
  finally
    myVerzList.Free;
  end;
end;


Postscriptum: Inladen wordt maar 1 maal gedaan ....

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Verwijderd schreef op 02 november 2002 @ 10:29:
en als ik de list nu public maak ?? worden we daar beter van ??
Nee

We adore chaos because we like to restore order - M.C. Escher


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Verwijderd schreef op 02 november 2002 @ 10:39:
:'( ... ik maak nu een nieuwe Tlist aan ... en gebruik deze vervolgens.. maareh .. probleem is er alleen maar erger op geworden.. wat doe ik fout ???
Niets in dat stuk. De fout blijft omdat je het probleem niet aangepakt hebt.

Variablen die je declareerd in een functie zijn lokaal voor die functie. Die worden weer vrijgemaakt als je de functie uit gaat.

Als je
Getal := SomeFunction;
aanroept wordt het resultaat van die functie in Getal gekopieerd en daarna vrijgemaakt omdat de functie teneinde is. Maar aangezien Getal een copy is kan je gewoon verder werken. Bij Strings gaat het ook goed omdat deze reference counted zijn. Delphi maakt er zelf een copy van. Als je in een functie
Result := TObject.Create;
doet gaat het ook goed want je maakt m niet vrij. Wat je teruggeeft is de pointer naar dat object. Niet het hele object zelf.
Maar als je een record gebruikt dmv
var MyRec: TMyRec;
wordt er ook geheugen gereserveerd, maar aan het einde van de functie weer automatisch vrijgemaakt. Wat je doorgeeft met
Result := MyRec;
is weer de pointer alleen. Deze wijst na het sluiten van die functie nergens meer heen.

Stel je voor dat TVerzameling geen record is maar een TObject. Dan doe je eigenlijk het volgende:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function TForm1.VulVerzamelingList(myBlok: TBlokje): TVerzameling;
var
  TempVerzameling : TVerzameling;
  Stuknr,row,col : Integer;
begin
  TempVerzameling := TVerzameling.Create;

  for Stuknr := 0 to 7 do
    for row := 0 to 4 do
      for col := 0 to 4 do
        TempVerzameling[Stuknr][row][col] := myBlok[row][col];

  Result := TempVerzameling

  TempVerzameling.Free;
end;

Begrijp je nu waarom het niet werkt zoals je het nu doet?

We adore chaos because we like to restore order - M.C. Escher


  • MaxxRide
  • Registratie: April 2000
  • Laatst online: 09-01 10:13

MaxxRide

Surf's up

var MyRec: TMyRec;
wordt er ook geheugen gereserveerd, maar aan het einde van de functie weer automatisch vrijgemaakt. Wat je doorgeeft met
Result := MyRec;
is weer de pointer alleen.
Wat je zegt is niet correct, als je een record type of ander 'simpletype' doorgeeft als parameter of al result wordt de waarde gekopieerd. Als je dus een TVerzameling = array[0..1] of Integer hebt dan wordt deze waarden gekopieerd. Het probleem ligt dan ook ergens anders in de code van jumpmaster.

Namelijk: in de functie inladen gebruik je de hele tijd dezelfde lokale var voor tverzameling en geeft je ettele malen hier de pointer van door naar de TList. Echter, dit is een lokale variabele, en die wordt idd aan het einde van de functie weggehaald, de pointers die jij in je TList zet wijzen dus nadat de functie InLaden naar een stuk geheugen dat helemaal niet meer van jou is!

Je zult dus iedere keer een nieuw item aan moeten maken in je TList van het type TVerzameling en dat geheugen moeten reserveren.

Denk er eens goed over na :)

(Het is igg niet het probleem dat je result := Tempverzameling in VulVerzamelingList een pointer doorgeeft, deze geeft netjes een kopietje)

Dat kun je testen met die demo proggie:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function TForm1.getGevuldeVerzameling(pOffset: integer): TVerzameling;
var
  lVerzameling: TVerzameling;
  i : integer;
begin
  for i := 0 to 9 do
  begin
    lVerzameling[i] := i+pOffset;
  end;
  result := lVerzameling;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  lVerzameling1, lVerzameling2: TVerzameling;
  i : integer;
begin
  lVerzameling1 := getGevuldeVerzameling(0);
  lVerzameling2 := getGevuldeVerzameling(5);
  for i := 0 to 9 do
  begin
    ShowMessage(IntToStr(lVerzameling1[i]) + ' .. '+IntToStr(lverzameling2[i]));
  end;

end;

[ Voor 0% gewijzigd door MaxxRide op 02-11-2002 11:49 . Reden: code even in code tags gezet, oeps.... ]

If you are not wiping out you are nog pushing enough...


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Pinda schreef op 02 november 2002 @ 11:48:
[...]


Wat je zegt is niet correct, als je een record type of ander 'simpletype' doorgeeft als parameter of al result wordt de waarde gekopieerd. Als je dus een TVerzameling = array[0..1] of Integer hebt dan wordt deze waarden gekopieerd. Het probleem ligt dan ook ergens anders in de code van jumpmaster.

Namelijk: in de functie inladen gebruik je de hele tijd dezelfde lokale var voor tverzameling en geeft je ettele malen hier de pointer van door naar de TList. Echter, dit is een lokale variabele, en die wordt idd aan het einde van de functie weggehaald, de pointers die jij in je TList zet wijzen dus nadat de functie InLaden naar een stuk geheugen dat helemaal niet meer van jou is!
Inderdaad, je hebt gelijk van die records die als value doorgegeven worden.

Ik had aangenomen dat een records ook als een pointer doorgegeven werd. :)Resultaat is hetzelfde uiteindelijk.

We adore chaos because we like to restore order - M.C. Escher


  • MaxxRide
  • Registratie: April 2000
  • Laatst online: 09-01 10:13

MaxxRide

Surf's up

Ik heb een keer drie dagen naar een bug gezocht omdat ik ook dacht dat een record door werd gegeven als pointer ipv als value, dat is echt k*t.

resultaat is hetzelfde? Je ne sais pas....

If you are not wiping out you are nog pushing enough...


  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 18-08 10:58

Bergen

Spellingscontroleur

De TVerzameling moet dus een object worden ipv een record.

Delphi:
1
2
3
TVerzameling = class (TObject)
    FVerzameling: array [0..7, 0..4, 0..4] of Integer;
end;


Dan moet het na vele aanpassingen lukken :)

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Pinda schreef op 02 november 2002 @ 23:44:
resultaat is hetzelfde? Je ne sais pas....
De code blijft refereren mbv die TList naar een stuk geheugen dat er niet meer is. Of het nu doorgegeven is by reference of by value bedoelde ik.

We adore chaos because we like to restore order - M.C. Escher


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

GerbenW schreef op 03 november 2002 @ 00:07:
De TVerzameling moet dus een object worden ipv een record.
Je moet niets. Dat kan een oplossing zijn idd. Kijk dan ook even naar een TObjectList. Deze kan TObject afgeleiden opslaan en als hij ze Owned maakt ie ze zelfs voor je vrij.

Je kan ook gewoon in je functie VulVerzamelingList elke keer PVerz := new TVerzameling; doen en die dan returnen. En niet vergeten vrij te maken aan het eind natuurlijk :) Of nog mooier gewoon al een gecreerde PVerz door geven aan VulVerzamelingList.

We adore chaos because we like to restore order - M.C. Escher


  • jvdmeer
  • Registratie: April 2000
  • Nu online
Waarom doe je in plaats van:
Delphi:
1
2
  TVerzameling = array[0..7, 0..4, 0..4] of Integer;
  TBlokje = array[0..4, 0..4] of Integer;


niet:

Delphi:
1
2
  TBlokje = array[0..4, 0..4] of Integer;
  TVerzameling = array[0..7] of TBlokje;


Dan is in 1 keer duidelijk wat TVerzameling inhoudt, en wat de relatie tussen TBlokje en TVerzameling is.

  • freddifish
  • Registratie: November 2000
  • Laatst online: 29-01 09:15

freddifish

schnappi !

inderdaad ik mis ergens toch wel de new(pointer) je moet die wel ergens expliciet aanmaken bv bij het inladen.

'people say I'm a drinker, but I'm sober half the time' - Mick Jagger | mail: freddifish_AT_gmx.net

Pagina: 1