Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Dynamische Arrays...Übergabe


Flamefire - Fr 10.07.09 12:16
Titel: Dynamische Arrays...Übergabe
Ich habe folgende Situation:
Eine funktion liefert als RückgabeTyp ein dynamisches ByteArray

Delphi-Quelltext
1:
2:
3:
4:
function foo():TDynByteArray;
begin
SetLength(Result,100);
end;

das weise ich einer variable zu:

Delphi-Quelltext
1:
temp:=foo();                    

was passiert jetzt, wenn ich nochmal temp:=foo(); mache?
hab ich dann das vorherige array verloren (memleak?)
und was ist mit:

Delphi-Quelltext
1:
2:
temp:=foo();
temp2:=temp;

habe ich dann 2 mal den speicher des arrays, oder sind temp und temp2 nur pointer auf das array und nur der pointer wurde kopiert?


ffgorcky - Fr 10.07.09 13:19

Also entschuldige, falls das nicht so ist, aber eigentlich müsste Deine Frage doch mit diesem Thread
Dynamisches Array im record [http://www.delphi-forum.de/viewtopic.php?t=79048&start=0&postorder=asc&highlight=dynamisches+bytearray+pointer]
beantwortet sein - oder?
Sonst hättest Du Deine Frage doch auch dort anhängen können...

---Oder habe ich Dich jetzt total missverstanden?


bummi - Fr 10.07.09 16:08


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var
  a,b:TDynIntArray;
begin
   a := foo;
   a[10]:=10;
   b:=a;
   SetLength(b,0);
   Showmessage(IntToStr(a[10]));
   Showmessage(IntToStr(High(b)));
   Showmessage(IntToStr(High(a)));
end;


bissel so wie bei Strings ....

Moderiert von user profile iconGausi: Delphi-Tags hinzugefügt


Marc. - Fr 10.07.09 17:00

Kleines Beispiel, hoffe dass ich mich hierbei nun nicht vertan habe. ;)

Delphi-Quelltext
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:
type
  TDynArray = Array of Integer;

function Foo(ALength: Integer): TDynArray;
begin
  SetLength(Result, ALength);
end;

procedure Demo;
var
  dA: TDynArray;
   p: Pointer;
begin
  dA := Foo(150); // Length dA = 150
  Pointer(TDynArray(p)) := @(TDynArray(dA)); // p Zeiger auf dA
  dA := Foo(100);  // Length dA = 100

  ShowMessage(IntToStr(Length(TDynArray(p^)))); // Length = 100!

  TDynArray(p^)[150] := 2;

  ShowMessage(IntToStr(DWORD(p^)));  // $10530968
  ShowMessage(IntToStr(TDynArray(Pointer(DWORD(10530968)))[150])); // = 2; 4 Bytes davor korrekterweise 0!
  ShowMessage(IntToStr(dA[150])); // Die Struktur bleibt im Speicher noch erhalten,
                                  // bis der Bereich entweder überschrieben, mittels
                                  // SetLength(dA, 0) oder mittels Beenden des Programmes freigegeben wird! ;-)
end;

Edit: Ich muss zugeben, dass die Spielerei mit den Pointern im Grunde redundant ist... :P

Grüße,
Marc


BenBE - Fr 10.07.09 17:18

user profile iconMarc. hat folgendes geschrieben Zum zitierten Posting springen:
Kleines Beispiel, hoffe dass ich mich hierbei nun nicht vertan habe. ;)

Delphi-Quelltext
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:
type
  TDynArray = Array of Integer;

function Foo(ALength: Integer): TDynArray;
begin
  SetLength(Result, ALength);
end;

procedure Demo;
var
  dA: TDynArray;
   p: Pointer;
begin
  dA := Foo(150); // Length dA = 150
  p := @dA; // p Zeiger auf dA (BenBE: Etwas verkürzt)
  dA := Foo(100);  // Length dA = 100

  ShowMessage(IntToStr(Length(TDynArray(p^)))); // Length = 100!

  TDynArray(p^)[150] := 2//BenBE: AV weil Index out of Bounds

  ShowMessage(IntToStr(DWORD(p^)));  // $10530968 (BenBE: Undefined, weil uninitialisiert, liefert den Inhalt der ersten Adresse)
  ShowMessage(IntToStr(TDynArray(Pointer(DWORD(10530968)))[150])); // = 2; 4 Bytes davor korrekterweise 0! (BenBE: BLOSS NICHT!!!*)
  ShowMessage(IntToStr(dA[150])); // Die Struktur bleibt im Speicher noch erhalten,
                                  // bis der Bereich entweder überschrieben, mittels
                                  // SetLength(dA, 0) oder mittels Beenden des Programmes freigegeben wird! ;-) (BenBE: Index out of Bounds)
end;

Edit: Ich muss zugeben, dass die Spielerei mit den Pointern im Grunde redundant ist... :P

Grüße,
Marc


*Die Adresse eines Zeigers bekommt man mit DWORD(p) und nicht DWORD(p^). Letzteres ist der Wert der Speicherzelle, auf die der Zeiger zeigt als DWORD interpretiert.


Flamefire - Fr 10.07.09 17:50

also kurz: bei der neuen zuweisung eines arrays wird nur der pointer überschrieben. ich muss das alte array also vorher freigeben...