Autor |
Beitrag |
Heiko
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Fr 14.07.06 12:37
Hallo,
ich habe einen String und möchte den kopieren, allerdings mit GetMem etc., da ich den Zeiger brauch und der String sonst überschreiben wird  .
Nun ja, wie kopiert man es am besten (ohne ASM)?
Ich habs momentan so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| s: WideString; len: integer; s:='test'; len:=length(s)*2+2; GetMem(p, len); Move(s[1], p, len); |
Mich würde vor allem interessieren, wie man die Längenbestimmung optimieren kann, denn das ist noch nicht das gelbe vom Ei  .
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Fr 14.07.06 12:55
Ganz einfach..
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var s: String; s2: String; s := 'test'; s2 := s; UniqueString(s2); |
Gruß, Motzi
Edit: ich seh grad erst, dass du ja mit einem WideString arbeitest. In diesem Fall reicht eine einfache Zuweisung an die Variable die die Kopie enthalten soll - WideStrings haben keine Referenzzählung und sind immer unique!
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Fr 14.07.06 13:04
Gut zu wissen  . Aber leider ist es nicht ganz die Lösung meines Problems. Und zwar bringen mir zusätzliche Variablen nichts, da ich vorher nicht weiß, wieviel ich brauchen werde. Ich wollte mir jetzt immer nur die Zeiger auf die Strings speichern, sprich statt einer Variable dauernd den WideString zu übergeben, und damit den alten Inhalt zu löschen, brauche ich eben etwas, womit immer ein neuer Speicherbereich verwendet wird.
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Fr 14.07.06 13:05
Sorry, das versteh ich nicht ganz.. erklär nochmal genauer und vielleicht auch mit dem Hintergrund warum du das so machen willst. Vielleicht findet sich eine andere/bessere Lösung.
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Fr 14.07.06 13:44
Und zwar geht es um meine Unit SearchTool (Festplatte nach Dateien durchsuchen). Ich will jetzt probieren aus dem rekusiven Verfahren ein iteratives zu machen (ob es Performancevorteile ergibt, da keine "sinnlosen" Stufen entstehen). Um das zu realisieren reserviere ich mir immer 104 Bytes. Die ersten 100 Byte sind als Platzhalter für 25 Pointer auf die WideStrings gedacht und die letzten 4 Bytes für einen Pointer auf das nächste "104er-Element" (du weißt was ich meine  ). Das war es erst einmal zur "Speicherverwaltung".
Nun zum Suchalgorithmus. Die 104er-Elemente werden erst einmal auf 0en "resetet" (mit ZeroMemory). Wenn der Suchalgo nun einen Ordner findet, fügt er den Zeiger von dem WideString dem Element hinzu (der nächste gefundene Ordner nimmt dann die nächsten 4 Bytes etc. Und sobald die 25 Ordner voll sind, reserviert er sich ein neues Element und fängt dort wieder von vorne mit dem befüllen fort). Und diese Ordner durchsucht er nach und nach.
So das wäre das wichtigste zum Verfahren. Also das Problem, um das es hier geht, ist das im Zweiten Absatz beschriebene.
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Fr 14.07.06 13:58
Ok.. dann würde ich zu den APIs SysAllocString und SysFreeString raten...
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Fr 14.07.06 14:05
In welcher Unit sind die? (Delphi findet die nicht, aber auch in der Delphi-Hilfe sind sie nicht enthalten  )
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Fr 14.07.06 14:16
Das sind Windows-APIs, die wirst du nicht in der Delphi-Hilfe finden. Die Dokumentation findest du im MSDN: SYSALLOCSTRING SYSFREESTRING
Die beiden Funktionen sind in der Unit "ActiveX" definiert.
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Fr 14.07.06 14:21
Ahh k, thx (da hatte ichs ja nur in der anderen Unit ausprobieren müssen, da dort ActiveX automatisch dabei ist  ). Ich probiers jetzzt mal aus, obs so funzt, wie ichs will
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: So 23.07.06 14:47
Hallo Motzi,
ich bin jetzt soweit, das ich die beiden Befehele benötige. SysAllocString funktioniert so, wie ichs brauch, aber SysFreeString funktioniert irgendwie nicht, was ich seltsam finde. Muss ich da etwas zusätzliches beachten?
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: So 23.07.06 14:52
Was genau meinst du mit "funktioniert nicht"?
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: So 23.07.06 15:23
Nun ja, über SysAllocString werden ca. 42 MB (wovon ich selber per GetMem nur 376 KB reserviere, der rest also auf SysAllocMem geht) reserviert, und er dann nichts wirklich freigibt, obwohl er die Freigebe-Routine durchläuft. Er geht am Ende ca. 1 MB nur wieder nach unten, und das müsste der Teil sein, den ich selber per GetMem reserviert hatte (also die 376 KB). Erst wenn das Programm beendet wird, wird der RAM freigegeben (vermutlich von Windows, der den datenmüll erkennt  ).
PS: Die zahlen waren nur auf die Auslagerungsdateien bezogen. Im Physikalischen Speicher verhält es sich so ähnlich  .
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: So 23.07.06 17:41
Es ist oft so, dass der reservierte Speicher zwar freigegeben wird, dies aber nicht immer sofort angezeigt wird (zB im Taskmanager). Versuch mal was passiert wenn du das Programm minimiertst. Oft zeigt der Taskmanager dann auf einmal schlagartig nur mehr einen Bruchteil der Speicherauslastung an...
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: So 23.07.06 17:48
Mhm, das bringt leider auch keine Änderung. Ich ahbe mal den Code soweit abgespeckt, dass du keine extra Kompos brauchst, um dir mal den soucre anzusehen und aus zu probieren  .
PS: Mich wundert es gerade, dass in der abgespeckten Version noch ein Systemerror kommt, ka wieso  . (Erst ab dem 2. Durchlauf)
Einloggen, um Attachments anzusehen!
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: So 23.07.06 18:51
Muss es mir erst genauer anschaun, aber auf den ersten Blick gibt es einige Dinge die mir ganz und gar nicht gefallen (vor allem im Bezug auf den Thread)..!
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: So 23.07.06 19:51
Motzi hat folgendes geschrieben: | vor allem im Bezug auf den Thread..! |
Nun ja, ich arbeite normalerweise mit der Klasse TThread und nicht mit BeginThread etc.  , und wie gesagt, ich habe einiges weggenommen in der Demo, damit du nur das nötigste hast. Ich hasse es nur an Threads, das man auf Komponenten eigentlich überhaupt nicht zugreifen darf, ich es aber meistens doch mache, wiel ich kein Bog habe immer alles über Synchronisation oder Messages zu machen (ich bevorzuge Messages  ).
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mo 24.07.06 15:30
Ich hab mal deinen Code komplett überarbeitet und dir einen Thread direkt in die Klasse eingebaut..  Schaus dir mal an wenn falls du noch Fragen dazu hast zöger nicht..!
Gruß, Motzi
Einloggen, um Attachments anzusehen!
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
Heiko 
      
Beiträge: 3169
Erhaltene Danke: 11
|
Verfasst: Mo 24.07.06 17:10
k, erst einmal danke, dass du für mein Problem dir Zeit genommen hast  .
Bei den Thread sachen muss ich erst einmal gucken, was vereinzelte Befehele genau machen (dadurch das ich in bestimmten Bereichen die Fehlerwahrscheinlich für extrem gering halte, habe ich mich da eben nicht drum gekümmert  ).
Aber eine kleine Frage zu Threads allegmein habe ich dennoch. Wenn 2 verschiedene Threads gleichzeitig auf einen Pointer zugreifen, der eine liest (kann damit ja keinen Schaden anrichten) und der andere schreibt (beim schreiben kann es ja zu Fehlern im 1. Thread kommen, da er ja gleichzeitig liest), tritt das Problem erst auf, wenn mehr als 4 Bytes geändert werden, oder kann es passieren, dass der eine dann eine Mischung der beiden Pointer hat (z.B. die ersten beiden Bytes neu und die anderen beiden noch alt)? Das bei größeren Strukturen ein Problem besteht ist mir klar, nur eben bei den 4 Bytes nicht, da ja der Processor mit 32-Bit arbeitet, also ob er auch immer 4-Byte-weise schreibt.
@Zeigern: Ist GetMemory haargenau das gleiche wie GetMem, nur dass bei dem einen der Output als Paramater ist, und der andere als Funktionsrückgabe (die Delphihilfe von D2005 schweigt leider im Index über diese Befehle  )?
Und das ich an einigen Stellen das ^ hinter der Variable vergessne hatte, leigt einfach daran, dass ich mir das mit den Zeigern zwangslaufig alleine erarbeitet hatte (wir sind auf VirtualStringTree umgestiegen, wo das meiste mit Zeigern ist, und man eben ein ganz kleines bissl davon braucht), dadurch fehlen mir noch vereinzeltes Grundwissen zu Zeigern (Var^ war eigentlich die einzigste Variante, die ich nicht kannt, denn ansonsten gibt es ja meines Wissens nach nur noch @ und ^Typ  ). (Und was Zeiger sind etc. weiß ich ja so  ).
@Das eigentliche Problem: Nun ja, leider bringt dein Code auch keine Speicherfreigabe  . Von dem was ich so gesehen habe, läuft es ja immer noch so ab, wie ichs hatte.
PS: Die Freigabe, so wie du es umgestaltet hast, dürfte langsamer sein, als die die ich hatte  . Ich habe eben gewisse Überprüfungen weggelassen, da SysFreeString(0) nichts macht (laut MSDN), von daher ist die Überprüfung auf o (nil) unnötig.
|
|
Ecki
Hält's aus hier
Beiträge: 2
Windows 2000/XP
Delphi 7
|
Verfasst: Mo 18.09.06 21:43
Hallo,
ich versteh dein Problem zwar nicht ganz, aber nach meiner Erfahrung tun es die dynamischen Array´s von Delphi ganz gut. Ich verwende einfach Array of String. Wenn du Platz benötigtst, dann schreib einfach
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var sa: array of string; begin ...
if i>high(sa) then Setlength(sa, high(sa)+1000)
sa[i] := ... |
und wenn Du fertig bist:
Delphi-Quelltext
Damit werden immer Blöcke z.B. von 1000 reserviert. Das kann man noch ein bischen schöner schreiben, aber so gehts. Deine Pointerverwaltung braucht ja auch was Zeit, und ich würde die Sachen einfach mal in einer Schleife gegeneinander vergleichen. Manchmal ist das schon überraschend...
Ist natürlich keine Garantie, das es schneller ist.
Meistens liegt das Problem sowieso in unnötigen String-Zuweisungen oder Konvertierungen. Setz mal einen Breakpoint in deine Routine und schau Dir das CPU-Fenster an. Der Assembler-Coder mag vielleicht nicht gut lesbar sein, aber unnötige Aufrufe findest Du schon.
Gruß, Ecki
Moderiert von Christian S.: Delphi-Tags hinzugefügt
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Mo 18.09.06 22:38
Hi Heiko,
Wenn Du dein Stringproblem in einem kleinen Beispielcode packen kannst, dann können wir gemeinsam eine performantere Lösung suchen. Damit meine ich nicht deine Demo, sondern ein kleines Testprogramm, das deine Widestring-Datenstrukutr beinhaltet.
_________________ Na denn, dann. Bis dann, denn.
|
|