Autor Beitrag
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Mo 21.03.05 16:05 
ja, wird dieser denn aber nicht trotzdem freigegeben ?
SchelmVomElm
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 154

W2K Pro
D5 Pro
BeitragVerfasst: Mo 21.03.05 16:07 
Wenn ich einen hätte würd ich ihn auch posten. Und wenn man es schon nicht besser weiss, würde ich erst recht davon ausgehen dass ein Speicherleck gibt und mich drum kümmern. Gehört sich einfach so.

_________________
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("|"+(*u/4)%2);
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Mo 21.03.05 16:07 
Aber mit @ holst du dir den Offset der variable.
Klar, daß @p dann nicht gleich @s, das sind zwei völlig verschiedene Variablen.

Um so mehr, wird Delphi sich selbstständig um p kümmern und dabei spielt es keine Rolle wohin der Zeiger zeigt.

Achja, ganz nebenbei hier mal n Auszug aus der Hilfe:
Zitat:

Ein PChar ist ein Zeiger auf einen nullterminierten String mit Zeichen des Typs Char. Jeder der drei Zeichentypen besitzt einen integrierten Zeigertyp:

PChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PAnsiChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PWideChar ist ein Zeiger auf einen nullterminierten String mit 16-Bit-Zeichen.

PChars bilden mit kurzen Strings den ursprünglichen String-Typ von Object Pascal. Sie wurden als Kompatibilitätstyp zur Sprache C und zur Windows-API eingeführt.


//Edit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  s: string;
  p: pchar;
begin
  s := 'test';
  p := pchar(s);

  if pointer(p) = pointer(s) then showmessage('gleich');
end;


Ich verpeil eh grad alles.. *ne kippe rauchen geht*

_________________
Stellen Sie sich bitte Zirkusmusik vor.
SchelmVomElm
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 154

W2K Pro
D5 Pro
BeitragVerfasst: Mo 21.03.05 16:13 
user profile iconopfer.der.genauigkeit hat folgendes geschrieben:
Aber mit @ holst du dir den Offset der variable.
Klar, daß @p dann nicht gleich @s, das sind zwei völlig verschiedene Variablen.

Um so mehr, wird Delphi sich selbstständig um p kümmern und dabei spielt es keine Rolle wohin der Zeiger zeigt.

Achja, ganz nebenbei hier mal n Auszug aus der Hilfe:
Zitat:

Ein PChar ist ein Zeiger auf einen nullterminierten String mit Zeichen des Typs Char. Jeder der drei Zeichentypen besitzt einen integrierten Zeigertyp:

PChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PAnsiChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PWideChar ist ein Zeiger auf einen nullterminierten String mit 16-Bit-Zeichen.

PChars bilden mit kurzen Strings den ursprünglichen String-Typ von Object Pascal. Sie wurden als Kompatibilitätstyp zur Sprache C und zur Windows-API eingeführt.


//Edit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  s: string;
  p: pchar;
begin
  s := 'test';
  p := pchar(s);

  if pointer(p) = pointer(s) then showmessage('gleich');
end;


Ich verpeil eh grad alles.. *ne kippe rauchen geht*



Der Sinn dieses Postings ist mir nicht klar - auch wenn ich mir dabei Zirkusmusik vorstelle! :mrgreen:

_________________
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("|"+(*u/4)%2);
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Mo 21.03.05 16:30 
Eigentlich bezieht sich das auf die letzte Aussage von retnyg
und soll ausdrücken, daß p hier nicht freigegeben werden muß.

_________________
Stellen Sie sich bitte Zirkusmusik vor.
retnyg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2754

SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
BeitragVerfasst: Mo 21.03.05 16:35 
variablen werden vom delphi-compiler von haus aus selber freigegeben, mit Dispose gibt man Objekte frei.
aber woher soll der compiler wissen, wo der freizugebende pchar im speicher ist, wenn der zeiger drauf verändert wird ? ich glaub nicht dass für jede variable zwei pointer gespeichert werden.

_________________
es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mo 21.03.05 17:11 
Es kommt drauf an, wie der String gespeichert ist. Bei "hardcoded" Strings ist es anders als bei Strings, die intern mit GetMem erzeugt wurden. Hier einige Beispiele, die das verdeutlichen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
Var
 S : String;
 P : PChar;
begin
 S := 'abcdefg'// hardcoded
 P := PChar(S);  // hier wird eine Kopie erstellt
 S[2] := 'B';
 ShowMessage(P); // abcdefg

 S := 'abcd';    // hardcoded
 S := S + 'efg'// hier wird eine Kopie des Strings erstellt (mit GetMem)
 P := PChar(S);  // hier gibt's keine erneute Kopie mehr
 S[2] := 'B';
 ShowMessage(P); // aBcdefg
end;
Siehe z.B. auch hier: Reverse (Hier wird ein PChar-Pointer ebenso verändert).
Ich wage mal zu behaupten, dass bei nicht hardgecodeten Strings gilt: p := PChar(S) ist äquivalent zu p := @S[1].
Könnte mich aber täuschen, das hier basiert lediglich auf Beobachtungen....

Übrigens hab ich oben (weiss nicht mehr wo) einen Denkfehler gesehn: p ist natürlich nie gleich @S!
Wenn p am gleichen Ort gespeichert ist wie S, dann gilt: p=@S[1].
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Mo 21.03.05 17:41 
user profile iconretnyg hat folgendes geschrieben:
variablen werden vom delphi-compiler von haus aus selber freigegeben.


Jup, und was anderes als ne Variable ist es nicht.
ausblenden volle Höhe 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:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
var
  p1,
  p2,
  p3,
  p4: pointer;
  pc: pchar;
  s : string;
  c1,
  c2: char;
begin
{
pc ist unsere variable, die den zeiger kennt.

daß pc vom typen pchar also der enthaltene zeiger auf einen char zeigt, ist dabei unerheblich.

@pc gibt den offset auf die variable p, also unseren eigentlichen pointer auf pc.
pointer(pc) macht nen typcast in diesem fall und gibt uns den zeiger auf den char zurück.
also gilt pchar(pointer(pc)) = pc;
}

  s := 'TEST';

  pc := pchar(s);

  // p1 = p2 -> p1^ = p2^ = s[1];
  p1 := pointer(s); // zeiger von s -> char(p1^) = 'T'
  p2 := pointer(pc); // zeiger von pc -> char(p2^) = 'T'

  p3 := @s; // offset
  if p1 = pointer(p3^) then showmessage('gleich');
  p4 := @pc; // offset
  if p2 = pointer(p4^) then showmessage('gleich');

  // hier der beweis, daß der wert in der variable verändert wird,
  // aber der offset von pc nicht
  inc(pc);
  if @pc = p4 then showmessage('gleich');

  // ergo muß der compiler nix machen außer pc wie eine normale variable
  // z.B. integer, string etc. zu behandeln
end;


Moderiert von user profile iconTino: Delphi-Tags hinzugefügt.

_________________
Stellen Sie sich bitte Zirkusmusik vor.


Zuletzt bearbeitet von opfer.der.genauigkeit am Mo 21.03.05 17:45, insgesamt 1-mal bearbeitet
SchelmVomElm
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 154

W2K Pro
D5 Pro
BeitragVerfasst: Mo 21.03.05 17:42 
Zitat:
p := PChar(S) ist äquivalent zu p := @S[1]


Also wenn Du mit S einen Pascal string meinst kann das nicht sein, denn der muss keine Nullterminierung enthalten!

ausblenden Delphi-Quelltext
1:
2:
S := S + #0;
p := @S[1];

_________________
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("|"+(*u/4)%2);
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mo 21.03.05 17:49 
Der normale String (= implizit AnsiString) ist nullterminiert, obwohl du das nicht zu spüren bekommst!
Der ist unter Umständen sogar doppelt nullterminiert (wegen den WideChars!).
Wenn du's nicht glaubst, siehe system.pas!
retnyg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2754

SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
BeitragVerfasst: Mo 21.03.05 17:56 
fazit: in diesem speziellen fall wird kein speicherleck erzeugt (ausser ein hartgecodeter string wird DIREKT hergenommen, also nicht über einen prozedureaufruf), es ist aber gefährlich, zeigertypen herumzubiegen wenn man nicht genau weiss was man tut (und ich bin mir sicher dass das bei f34ar0fth3d4rk der fall war ;)), weswegen man es vermeiden sollte.
lieber manuell einen zeiger des typs pointer erstellen und dann mit diesem herumwerkeln...

_________________
es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Mo 21.03.05 17:56 
wenn man mehrere strings zusammenfügt, werden die nullen dann entfernt ?
kann ja sein, dass der string dadurch immer mehr bytes schluckt ?!

und der code war ja zuerst auch nur für das zeichen #0 gedacht, deswegen hats ja auch anfangs funktioniert, wenn man eigene trennzeichen nehmen will muss man das ende des strings extra abfragen, weil es nicht = trennzeichen ist
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mo 21.03.05 17:58 
Natürlich werden die Nullen zuerst entfernt. Wenn du wüsstest, was alles abgeht, wenn man zwei Strings addiert... Du würdest staunen! ;)
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Mo 21.03.05 17:59 
hatte bis jetzt noch nicht zeit und bock mir das anzuschauen, deshalb einige wissenslücken :D
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mo 21.03.05 18:05 
ausblenden Delphi-Quelltext
1:
2:
S := 'Hallo '+A+' und '+B+' '+IntToStr(I);
S := Format('Hallo %s und %s %d',[A,B,I]);

Was denkst du, welche Variante ist effizienter? Du ahnst absolut richtig ;)
Zugegeben, IntToStr ruft Format auf, aber auch ohne IntToStr ist die zweite Methode schneller....
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mo 21.03.05 19:06 
Daß mit festen Feldlängen sämtliche eventuell aufgetauchten Probleme gar nicht erst auftauchen würden, das merkt wohl keiner. 8) Das einzig brauchbare, was hier steht ist der Beitrag, von Delphifan, man könne bei Zahlen ruhig ein Trennzeichen verwenden.

Nur : wo liegt der Vorteil davon überhaupt ? Mir ist niemand bekannt, der sich heute noch auf CSV einläßt, nur weil in den 50er Jahren irgendjemand mal bei 8-Bit Zeichensätzen sich ein seltenes Zeichen dafür ausgedacht hat.

_________________
Gruß
Hansa
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mo 21.03.05 19:12 
Bei festen Feldlängen gibt's dafür andere Probleme: Sie sind weniger gut editierbar, und es kann vorkommen, dass man plötzlich zu wenig Pla
retnyg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2754

SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
BeitragVerfasst: Mo 21.03.05 19:14 
würde ich nicht sagen, csv ist immer noch die einfachste möglichkeit ne datenbank zu erstellen.
n paar werte mit 10 zeilen code in ne csv schreiben, die kann dann mit excel geöffnet werden und man hat alle werte in den richtigen spalten.

_________________
es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...
hansa
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3079
Erhaltene Danke: 9



BeitragVerfasst: Mo 21.03.05 19:52 
Ich gebe es bald auf. Angenommen 3 Integer stehen in einer Zeile. Jede hat 10 Stellen. Ein paar Werte auslesen aus einer Textdatei geht dann so :

nicht CSV :

ausblenden Delphi-Quelltext
1:
2:
3:
Zahl1 := StrToInt (copy (zeile,1,10));
Zahl2 := StrToInt (copy (zeile,11,10));
Zahl3 := StrToInt (copy (zeile,21,10));


mit CSV und keiner festen Feldlänge sähe es z.B. so aus :

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
SemikolonPos := pos (';',Zeile);
HilfStr := copy (zeile,1,SemikolonPos-1); // String bis zum ersten Semikolon umkopieren
Zahl1 := StrToInt (copy (HilfStr,1,10));
delete (zeile,1,SemikolonPos);            // bereits umgewandelten TeilString entfernen.

SemikolonPos := pos (';',Zeile);
HilfStr := copy (zeile,1,SemikolonPos-1); 
// String bis zum jetzt ersten Semikolon umkopieren
Zahl2 := StrToInt (copy (HilfStr,1,10));
delete (zeile,1,SemikolonPos);            // bereits umgewandelten TeilString entfernen.

SemikolonPos := pos (';',Zeile);
HilfStr := copy (zeile,1,SemikolonPos-1); 
// String bis zum jetzt ersten Semikolon umkopieren
Zahl3 := StrToInt (copy (HilfStr,1,10));
delete (zeile,1,SemikolonPos);            // bereits umgewandelten TeilString entfernen.


Handelt es sich nicht um Zahlen, dann hat man sowieso wohl verloren, denn man stelle sich mal vor, irgendjemand stellt aus Versehen die Tastatur auf englisch um. Er will eingeben : "östlich" und wegen geringer Schreibmaschinenkenntnisse achtet er mehr auf die Tastatur als auf das was tatsächlich da steht. Und das ist dann ";stlich".

Jetzt kommt alles mitsamt unbewußten Schreibfehlern in eine Datei und das Programm achtet nur auf ; Da ist aber jetzt einer zuviel drin und das Programm läuft nicht bis zum Ende durch. Die bewußte Eingabe des Trennzeichens ist dabei noch völlig außer acht gelassen.

Nimmt man ein anderes "Trennzeichen", so wird sich kaum was ändern. Es kracht irgendwann doch.

Das Argument mit Excel ist übrigens auch nur Theorie. Das kommt mit falschen Zeichen in einer "CSV" Datei genauso wenig zurecht, wie jedes andere Programm auch.

Der nächste Nachteil ist, daß man im Fehlerfall einen Editor getrost vergessen kann. In einer Textdatei ein ; zuviel zu entdecken ist fast unmöglich.

_________________
Gruß
Hansa
retnyg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2754

SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
BeitragVerfasst: Mo 21.03.05 20:07 
den zwoten codeteil kannst du dir sparen wenn du die explode funktion nimmst.
klar ist csv fehleranfällig wenn in texten semikolons vorkommen können.
wenn dies aber nie der fall sein wird, kann man das getrost verwenden.
bsp.: ich hatte mal ein ping-programm geschrieben das alle hosts eines subnetzes anpingt, und dann jeweils die hostnamen, ip-adresse und roundtrip time in ein csv schreibt.
die csv dann in excel geöffnet und schon hat man eine tabellierte übersicht aller rechner im netz.

_________________
es gibt leute, die sind genetisch nicht zum programmieren geschaffen.
in der regel haben diese leute die regel...