26. marts 2004 - 18:15Der er
9 kommentarer og 2 løsninger
Pointer problem
Davs...
Jeg har et lille problem med pointers i delphi. Jeg forsøger med nedstående kode at overfører et dynamsik array fra LoadConfig til FormCreate via Pointers, men kan ikke få det til at virke. Hvad skal jeg gøre for at få indeholdet af heads overført til headGroups???
På forhånd tak rrm
Kode:
headGroup er en record og headsGroups er et array af headGroup.
function LoadConfig(errHandle: hWnd): Pointer; var heads: array of headGroup; ... begin ... Result := @heads; end;
procedure TfrmMain.FormCreate(Sender: TObject); var tmp: Pointer; begin ... tmp := LoadConfig(frmMain.Handle); if(tmp <> nil) then headGroups := tmp else begin MessageBox(frmMain.Handle, 'Opstarts fejl', 'Fejl',MB_OKERROR); halt; end; ... end;
Den moderne arbejdsplads er i stigende grad afhængig af mødelokaler til at fremme samarbejde, men dette skift medfører også stigende sikkerhedsudfordringer.
Dit (et af dem) problem ligger i at din variable heads bliver deallokeret når du forlader din LoadConfig function - dvs. at din pointer peger på noget garbage..
Delphi holder ellers styr på en reference count på dynamic arrays - men det GÆLDER IKKE når du f.eks. sætter en pointer til at pege på et sådant.
Hvis du skal gøre det på denne måde kan du gøre følgende:
type THeadGroupArray = array of HeadGroup;
function LoadConfig(bla bla) : THreadGroupArray; var heads : THeadGroupArray; begin .. Result := heads; end;
procedure TfrmMain.... var tmp : THeadGroupArray; begin tmp := LoadConfig(...); ... ... end;
I øvrigt er det en meget dårlig ide at benytte untyped pointers fordi compileren ikke har en negermands chance for at vide hvad du peger på - og derfor ikke kan hjælpe dig særlig meget at fange fejl..
pointer typen skal kun benyttes, hvis du virkelig ikke har andre muligheder - og jeg vil næsten sig, at det så skyldes dårligt design.
Jeg vil bare lige nævne at jeg oftere og oftere benytter untyped pointers... det er måske lidt af dovenskab, da jeg ikke gider at lade mit kode være fyldt med en mase "ligegylige" defineringer! Men du har RET vær varsomt, og undgå at bruge untyped pointers, hvis du ikke rigtigt er vant til dem!!!!! :))
Ok - det skal jeg huske, lige et lille spørgsmål mere: Ved en pointer kan man checke om den er sat ved at se om den er nil, er der også en måde at teste om en bruger definere variable (dette tilfælde en record) er sat???
Med fremkomsten af objekter svandt behovet for at bruge records, til et absolut minimum. Også her ville jeg lave den sædvanlige konstallation af en TheadGroup klasse og en TObjectList som jeg har nedarvet til at indeholde THeadGroups - det er bare een unit og du kan fylde al mulig intelligens ind i objektet, såsom streaming funktionalitet.
Desuden er det dynamisk og frigiver du en TObjectList så sørger den selv for at frigive sine "Items" (i øvrigt uanset hvad du skriver i listens Create). Det er så' nemt og det virker altid.
Du vil i øvrigt finde, at specielt untyped pointers får Delphi 8 spytte warnings ud som var det en C++ compiler! Det er ikke god skik.
Din kode har jeg modificeret til nedenstående hvis jeg ikke kan overtale dig til at køre med lister og klasser i stedet:
type TGroup = packed record id : integer; valid : boolean; end;
procedure TfrmMain.Button1Click(Sender: TObject); var Heads : THeadGroups; begin CreateGroup(Heads,10); // og det er jo analogt til SetLength ... end;
Alternativt kan du vist også gøre det således:
type HeaderGroup = packed record ... end;
THeads = array of headGroup; TPHeads = ^THeads;
function LoadConfig(errHandle: hWnd): TPHeads; begin GetMem(result); // Allokér pointer SetLength(result^,10); // Allokér 10 felter // fyld i' end;
procedure TfrmMain.FormCreate(Sender: TObject); begin // pHeadGroups = nil fra starten
pHeadGroups := LoadConfig(frmMain.Handle); if not assigned(pHeads) then begin MessageBox(Handle,'Opstartsfejl','Fejl',MB_OKERROR); // 'Opstartsfejl' er eet ord. PostQuitMessage(1); // Er bedre at bruge end Halt! end; end;
procedure TfrmMain.FormDestroy(Sender: TObject) begin if assigned(pHeadGroups) then begin // måske nødvendig med SetLength(pHeadGroups^,0); ??? FreeMem(pHeadGroups); end; end;
Bemærk endelig, at jeg ikke har testet det ret meget af det (en rigtig Microsoft disclamer, hva?).
Tak for svarene, mht. objecter vs record, så tror jeg ikke det kan betale sig at skifte, idet hver enkelt record kun skal indeholde ganske få data. Så derfor vil jeg benytte doc404 "metode".
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.