Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi StrAlloc verstehen (https://www.delphipraxis.net/96915-stralloc-verstehen.html)

Neutral General 1. Aug 2007 15:29


StrAlloc verstehen
 
Hi,

Habe mir gerade angeguckt wie man per Drag&Drop Dateien aus dem Explorer öffnet.. Habe soweit alles verstanden aaaber..

Delphi-Quellcode:
size := DragQueryFile(Msg.WParam, i , nil, 0) + 1;
Filename:= StrAlloc(size);
Man holt sich hier die größe des FilenameStrings... Wie das funktioniert habe ich mithilfe der Hilfe verstanden. Aber wie man nun nur durch die Größe an den eigentlichen String kommt nicht so ganz...
Ich kommentier mal soweit ich das nachvollziehen kann..


Delphi-Quellcode:
function StrAlloc(Size: Cardinal): PChar;
begin
  Inc(Size, SizeOf(Cardinal)); //warum?
  GetMem(Result, Size); // Speicher reservieren .. soviel wie der String lang ist
  Cardinal(Pointer(Result)^) := Size; // Size stellt die Adresse des Strings dar?
                                      // Hiermit wird doch der Pointer von Result auf die Adresse
                                      // die Size darstellt (mir fällt keine bessere Beschreibung ein)
                                      // "umgelenkt"
  Inc(Result, SizeOf(Cardinal));     // warum?
end;
Was ich daran nicht verstehe ist das Size sowohl die Länge als auch gleichzeitig die Speicheradresse des Strings darstellt.. Wenn der String 2 Zeichen lang ist.. dann müsste der String doch beim Offset 02 anfangen oder verstehe ich da was falsch?

Gruß
Neutral General

sirius 1. Aug 2007 15:36

Re: StrAlloc verstehen
 
Delphi-Quellcode:
function StrAlloc(Size: Cardinal): PChar;
begin
  Inc(Size, SizeOf(Cardinal)); //Die Größe des zu reservierenden Platzes um 4 Bytes erhöhen
  GetMem(Result, Size); // Speicher reservieren .. soviel wie der String lang ist + 4 Bytes um die Länges des Strings zu speichern
  Cardinal(Pointer(Result)^) := Size; //die Größe des Speicherplatzes am Anfang des reservierten Platzes speichern
  Inc(Result, SizeOf(Cardinal)); // Den Pointer (PChar) hinter die Größenangabe verschieben    
end;
Ein PChar sieht bei Delphi so aus, dass immer vor dem PChar 4 Bytes mit reserviert werden, welche die Länge des Strings beinhalten (+4)

Christian Seehase 1. Aug 2007 15:40

Re: StrAlloc verstehen
 
Moin Michael,

der Inhalt eines "normalen" Strings in Delphi beginnt bei der Adresse, die die Funktion zurückliefert.
Davor liegen dann noch 4 Byte (als Cardinal) Länge (und davor noch 4 Byte Referenzcount. Wo sind die eigentlich :gruebel:)

Delphi-Quellcode:
  // Platz schaffen für die Länge des zu reservierenden Strings
  Inc(Size, SizeOf(Cardinal));
  // Speicher reservieren für Länge und Inhalt
  // Result enthält jetzt die Adresse des reservierten Speichers
  GetMem(Result, Size);
  // An dieser Stelle wird jetzt die Länge gespeichert
  // Durch das ^ wird dereferenziert, also an die Adresse geschrieben, auf die Result zeigt.
  // Durch Cardinal() wird dann ein Type-Cast durchgeführt, damit man auch Size dorthin schreiben kann,
  // was der Compiler sonst unterbinden würde
  Cardinal(Pointer(Result)^) := Size;
  // Jetzt wird Result auf den Anfang des Inhaltes gesetzt
  // Die Länge steht also auf Result - 4
  Inc(Result, SizeOf(Cardinal));

thkerkmann 1. Aug 2007 15:42

Re: StrAlloc verstehen
 
Hi,

warum so kompliziert ?

Delphi-Quellcode:
...
var
  Filename: string;
...

   size := DragQueryFile(Msg.WParam, i , nil, 0);
   SetLength(Filename,size);
   size := DragQueryFile(Msg.WParam, i, pChar(Filename), 0);

...
ungetestet, müsste aber stimmen.

Gruss
[Edit thkerkmann] Mist, Thema verfehlt.... 6 setzen [/Edit]

Neutral General 1. Aug 2007 15:42

Re: StrAlloc verstehen
 
Ja gut was passiert hab ich jetzt verstanden aber der String könnte doch überall im Speicher sein.. Wieso zeigt Result standardmäßig schon am Anfang der Procedure (oder spätestens nach GetMem) auf das erste Zeichen des Strings ? (Müsste ja nach meinem Verständnis).

Wisst ihr was ich meine?

sirius 1. Aug 2007 15:45

Re: StrAlloc verstehen
 
Zitat:

Zitat von Christian Seehase
(und davor noch 4 Byte Referenzcount. Wo sind die eigentlich :gruebel:)

Ist ja kein String sondern ein PChar. Der hat keinen Referenzzähler :zwinker: .

Christian Seehase 1. Aug 2007 15:45

Re: StrAlloc verstehen
 
Moin Michael,

mit GetMem wird der Speicher reserviert, und die Adresse dieser Reservierung in Result abgelegt.

Der_Unwissende 1. Aug 2007 15:45

Re: StrAlloc verstehen
 
Hüstel verlesen, sorry!

Christian Seehase 1. Aug 2007 15:46

Re: StrAlloc verstehen
 
Sirius,

Zitat:

Zitat von sirius
Ist ja kein String sondern ein PChar. Der hat keinen Referenzzähler :zwinker: .

Schon, aber ein PChar braucht auch keine Länge... ;-)

sirius 1. Aug 2007 15:47

Re: StrAlloc verstehen
 
Zitat:

Zitat von Neutral General
Ja gut was passiert hab ich jetzt verstanden aber der String könnte doch überall im Speicher sein.. Wieso zeigt Result standardmäßig schon am Anfang der Procedure (oder spätestens nach GetMem) auf das erste Zeichen des Strings ? (Müsste ja nach meinem Verständnis).

Wisst ihr was ich meine?

Nö, der Zeiger zeigt nah GetMem auf den reservierten speicherplatz (inkl. der 4 Bytes) und wird am Ende (das "inc") einfach hinter die ersten 4 Bytes gelegt, also an den Anfang von [size] reservierten Bytes.

thkerkmann 1. Aug 2007 15:48

Re: StrAlloc verstehen
 
Zitat:

Zitat von Neutral General
Ja gut was passiert hab ich jetzt verstanden aber der String könnte doch überall im Speicher sein.. Wieso zeigt Result standardmäßig schon am Anfang der Procedure (oder spätestens nach GetMem) auf das erste Zeichen des Strings ? (Müsste ja nach meinem Verständnis).

Wisst ihr was ich meine?

Nee, der zeigt noch nicht auf deinen string....
StrAlloc hat erst mal nur Platz geholt - Du musst jetzt noch was reinschreiben.

Delphi-Quellcode:
  result := DragQueryFile(Msg.WParam, i , Filename, 0);
Gruss

sirius 1. Aug 2007 15:49

Re: StrAlloc verstehen
 
Zitat:

Zitat von Christian Seehase
Schon, aber ein PChar braucht auch keine Länge... ;-)

Bei Delphi schon. Denn dadurch kannst du einfach StrDispose(myPchar) machen, ohne dir die Länge gemerkt zu haben. Ist quasi ein "advanced PChar".

Edit: Und wenn du den PChar an C übergibst, meckert C auch nicht, wenn vor dem *Char noch ein Longint steht, welches die Länge des *Chars anzeigt (falls es voll gefüllt ist)

Neutral General 1. Aug 2007 16:01

Re: StrAlloc verstehen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Christian Seehase
Moin Michael,

mit GetMem wird der Speicher reserviert, und die Adresse dieser Reservierung in Result abgelegt.

Jaa aber wie kommen die Zeichen darein? Moment ich male euch mal was...

sirius 1. Aug 2007 16:03

Re: StrAlloc verstehen
 
Nach strAlloc liegt da auch nur Müll. Meist irgendetwas was du grad zuvor gemacht hast.

xaromz 1. Aug 2007 16:04

Re: StrAlloc verstehen
 
Hallo,

was meinst Du mit "wo der String schon drinsteht"? Da steht ja nirgends ein String. Du hast nur Speicher allokiert, der dann zur Speicherung eines Strings verwendet werden kann. Wenn Du also mit StrAlloc() Speicher anforderst, dann musst Du danach auch noch was damit machen...

Gruß
xaromz

Neutral General 1. Aug 2007 16:05

Re: StrAlloc verstehen
 
Ehm hat sich erledigt.
Hab jetzt gerade zum Schluss folgende Zeile vergessen:

Delphi-Quellcode:
DragQueryFile(Msg.WParam,i , Filename, size);
Das erklärt dann den Rest... Danke an euch alle ;)

Gruß
Neutral General

jbg 1. Aug 2007 17:43

Re: StrAlloc verstehen
 
Zitat:

Zitat von sirius
Bei Delphi schon. Denn dadurch kannst du einfach StrDispose(myPchar) machen, ohne dir die Länge gemerkt zu haben. Ist quasi ein "advanced PChar".

Falsch. Die 4 Bytes davor stammen noch von Turbo/Borland Pascal. Dort musste man bei FreeMem noch die Allozierungsgröße angeben. StrAlloc/StrDispose arbeitet nur so, weil es abwärts kompatibel ist, wie man an StrDispose mit dem FreeMem(P, Size) sieht. Die Länge für FreeMem kennt der Speichermanager selbst, da er diese Information selbst verwaltet, ggf. sogar direkt vor dem Reservierten Speicherbereich, wodurch folgendes entsteht:
[MemSize: 4 Bytes][Size: 4 Bytes][Data: (Size - 4) Bytes]


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:25 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz