Seite 2 von 5

Verfasst: 23.01.2006 17:19
von Toshy
@PMV
Also bevor ich teste erstmal folgendes.Ich wollte auch schon die Speicherverwaltung übernehmen, aber das ist ja nicht der sinn und zweck, das wollte ich mir ja extra ersparen. ich weiß moe wie lang die strings sind und muß die ständig ändern. dachte ich.
was ich nun nicht verstehe, ich wollte / müßte dann mit allcocate in ein long oder pointer schreiben. aber "\s" wäre doch dann die adresse in eine string zu schreiben. auf jedenfall nach der hilfedatei.
Kurze Erklärung wäre nett, damit ich es verstehe (teste gerade nebenbei und den string kann man anscheined auslesen).

Hmm, da hätte ich den Code vorher mal genau lesen sollen. Genau das soltle ja nicht geschehen. Die Strings sind dann ja doch wieder Pointer. Damit ist der Sinn und Zweck der Strukturen zum Großteil oder ganz verloren. Ok, da man den den Speicherbereich nun über die Namen der Strukturinhalte nutzen kann, ist es noch übersichtlicher, als wenn ich
*starID +(4*x) zum auslesen nehme. aber dennoch nicht so super toll.
gibt es denn keine Möglichkeit normal "Strings in Strukturen" zu nutzen und den Speicher freizugeben? Ich arbeite damit ja erst seit kurzem und denke / hoffe das ich da einfach nur noch etwas nicht weis.
Ich vermute aber das diese "verbiegen" der Strukturen in einen Speicherbereich mittels MEmory nicht angedacht ist.
Wäre schade, diese Vorlagen von euch sind nämlich ansonsten interessant.

@ts-soft
Ich weiß noch nicht genau wie du das jetzt meinst, besser gesagt mich verstanden hast. Das wenn ich Speicher mit PB freigebe (freememory oder einen string kürze) dann ist der natürlich sofort auch in Windows freigegeben. Aber so wie indem Beispiel von "NicTheQuick" (und danach von mir) geht es darum, das der Speicher in dem Beispiel Nicht freigegeben wird bzw. werden kann. So wie im langen Quellcode der Startpointer einer Struktur(variablen) geändert wird, so daß er auf einen Memorybereich zeigt geht es nur mit Speicherverlust, sobald die Struktur einen String beinhaltet (falls es anderes gibt, das noch nicht getestet).
Es ist auch an sich logisch, wenn nur EINE Strukturvariable erstellt wird zum Zugriff auf den Memorybereich, wohder soll diese eine Variable alle Positionen der Strings vermerken um sie zu löschen? Geht nicht.
Aber irgendwie dachte ich muß es doch gehen und sei es mit zwischenspeichern, aber da klappt nicht.

Da dieses schreiben in Memorybereiche per Strukturvariable Gang und Gebe ist (habe das schon oft gesehen in Codes) dachte ich mir, das dies eine korrekte Art der Anwendung ist und habe meine Code danach ausgerichtet. Aber das scheint so wohl nicht zu sein.

[edit]
wärend ich schrieb und testete haben schon wieder zwei von euch geschrieben,darauf antworte ich auch gleich.

Verfasst: 23.01.2006 17:48
von Toshy
@helpy und @PMV

Tja, dann also wie ich (wir vermutet) haben ist es korrekt, das dort was nicht freigegeben wird. und auch das warum hatte ich mir schön so in der art gedacht.
ich wundere mich über mich selbst, denn ich habe den anfangsverdacht gehabt ohne den code bei mir überhaupt einmal laufen zu lassen :-)

Aber das problem bleibt bestehen, gibt es da eine möglichkeit das mit Purebasic direkt zu lösen?
Das die gespeicherten (neu angelegten) Strukturen (die eigendlich immer die selbe ist) zurückkopiert werden und dann korrekt gelöscht geht ja nicht, weil es ja keine möglichkeit gibt strukturvariablen zu löschen. die existieren ja bis zum programmende.
Mit ASM kenne ich mich überhaupt nicht aus und würde das problem an sich wohl auch nicht lösen.

ACHTUNG!!
Was mir im Kopf noch eingefallen ist, könnte auch eine unangenehme Gefahrenquelle sein.
Ich vermute mal, das bei der "normalen Nutzung" einer Strukturvariablen beim ändern eines Strings in dieser ein neuer Speicherplatz dem String zugewiesen wird (wegen längenänderung, nicht immer, aber oft). der alte speicherplatz wird dann sicher korrekt freigegeben (sah bisher so aus).
zum freigeben, was nutzt PB da? Daten die es anhand des Stringpointers aus der Struktur liest oder anders? wenn es "über den bisherigen pointer" geht, dann würde sobald man die struktur auf einen memorybereich verbiegt ja ander daten enthalten, und wenn die nicht gerade NULL sind, dann könnte PB ja einen falschen speicherteil einfach freigeben, weil es vorhandene Daten im Grunde falsch interpretiert / muß.
Und wenn die Freigabe anhand einer internen Variable geschieht und so immer korrekt die zuletzt gesetzte strukturstringvariable (wat`n Wort) löscht, dann würde ja automatisch immer die zuletzt im memorybereich gesetzt variable (durch die sturktur gesetzt) gelöscht werden und so nicht genutzt werdne könne.
beides aber konnte ich so noch nicht bestellen, aber auch nur schwer testen. irgendwie scheint da wohl alles keine korrekte art der programmierungzu sein.

bei stings fällt das durch die große speichermenge n atürlich schnell ins gewicht, aber auch bei longs und floats usw. in strukturen könnte die verwaltung anders sein als im memory (also vielleicht auch noch interne variablen gesetzt und nicht nur der wert).

wenn es da also keine "offizielle" lösung gibt, dann scheint es gefährlich zu sein, strukturen zu verbiegen. selbst bei longs.

oder gibt es bei longs eine art von "offizieller Erlaubnis" das dies korrekt ist?

Danke Thorsten

Verfasst: 23.01.2006 18:10
von PMV
Puh ... also deinem letzten Beitrag konnt ich nicht so ganz folgen -.- ...

aber mit ASM kenn ich mich auch (noch) nicht wirklich aus, keine ahnung
ob sich das irgend wie ändert, daher würde ich diese Metode auch nicht
wählen. Wie schon gesagt mach ich das so wie ichs vorgeschlagen hab.
Im Prinzip ist diese Methode die selbe wie sie von PB praktiziert wird.

Wenn man

Code: Alles auswählen

Structure XYZ
  s.s
EndStructure
benutzt enthält die Structure selber nur einen 4 Byte großen Pointer zu
dem String, welches PB alles selber verwaltet. Durch mein Beispiel machst
du das alles Manuell. Du weist selber Speicher zu, verwaltest den Pointer
selber und rufst bzw änderst den String ebenfalls manuell.

Mit ReAllocateMemory() kannst du den benötigten Speicherplatz für deinen
String jederzeit vergrößern und verkleinern, sofern er sich ändert.

Mit dem folgenden Beispielcode ist es möglich einen Stringpointer für
sich selber jederzeit an zu passen oder neu zu erstellen, da neuer
Speicher reserviert wird, wenn anstelle des Pointers bei
ReAllocateMemory() Null übergeben wird.

Code: Alles auswählen

*Memory = ReAllocateMemory(*StringPointer, Len(Text$)+1)
IF *Memory ;ändert den Stringpointer nur, wenn alles glatt gelaufen ist
  *StringPointer = *Memory
  PokeS(*StringPointer, Text$)
EndIF
Damit sollte das Problem für jeden umgehbar sein, der das Thematisierte
Problem hat. Ich für meinen Teil benutzte dies schon ausgibig zum
speichern von Strings innerhalb von z.B. eigenen LinkedListen :D

Aber fals es da schnellere Möglichkeiten gibt, bzw. hier
Geschwindigkeitsverlust entsteht bin ich natürlich für alles offen :D

MFG PMV

Verfasst: 23.01.2006 18:46
von ts-soft
Um den Speicherplatz für Strings braucht man sich doch nicht kümmern, das macht PB doch alleine, deshalb ja auch die Begrenzung auf 63999 Bytes pro String.
PB reserviert autom. ein bestimmte Menge RAM für die Stringverwaltung, dieser wird erst bei Programmende freigegeben.

Verfasst: 23.01.2006 19:03
von PMV
Wenn das besagte Problem nicht wäre ok ... aber da PB nicht den
kompletten Speicherplatz wieder freigibt, sondern wegen "unwissenheit"
dies nicht tut steigt der Speicherplatz unaufhörlich an.

Bei höheren Mengen oder längerem laufen eines Programms wird somit
der reservierte Speicherplatz immer größer und PCs mit wenig Ram
werden dadurch merklich langsamer.

Macht man es also nun Manuell wird alles sauber Freigegeben und es gibt
keine Speicherplatzprobleme.

Ob ich das nun durch die manuelle Speicherplatzverwaltung für Strings
mache, oder ob da sich wer mit ASM auskennt und den von helpy
besagten ASM-Befehl nutzt ist egal. Aber es ist oft nicht zumutbar, über
das Speicherleck hinweg zu sehen und einfach zu sagen, "Dann schließ
das Programm doch einfach" :wink:

MFG PMV

Verfasst: 23.01.2006 19:15
von ts-soft
PB gibt am Programmende den kompletten Stringspeicher frei, sowie alle anderen Speicher auch. Strings können während des Programmlaufs nur durch Zuweisung eines Nullstrings ("") gelöscht werden.
Lediglich per API erstellte WindowsObjecte, wie Cursor, Brushes usw., sowie per API erstellte Speicher sind selber freizugeben.

Im Zweifelsfalle mach einfach FreeMemory(#PB_Any) :wink:

@ts-soft

Verfasst: 23.01.2006 20:07
von Toshy
Du hast uns oder das Problem nicht verstanden. Das nach beenden des Programmes alles wieder freigegeben ist, ist klar. Aber das hilft doch nicht, ich kann mein programm noch nicht alle 10-100 sekunden neu starten. Während des laufens tritt dabei nun mal ein Speicherleck auf (ist meiner meinung nach KEIN Bug) das man mit PB-Code nicht entgegenwirken kann. den code den ich lieferte bzw. nic... oder pmv haben das selbe problem. bei meinem code kommen ca. alle 10 sekunden 40 mb verloreneer ram dazu 300- 400 mb ram pro minute usw. das läßt sich nicht ändern es sei denn man nutzt das programm nicht so oder nimmt assembler. laß den code laufen und wenn du willst die 10 fache schleifendurchläufe und schau mal auf den belegten speicherplazt.

was bringt es uns, das nach programmende alles da ist, wenn wärend der laufzeit das programm abschmiert weil 4 gb virtueller ram in minuten voll sind.

außerdem scheint pb den speicherplatz für die interne variablenverwaltung nicht zu reservieren sondern dynamisch anzupassen.

PB an sich ist da sehr gut, wie in anderen dingen.
es wurde halt nur leider nicht daran gedacht, das man strukturen auch so nutzen könnte bzw. es wird auch nicht verhindert.


FreeMemory(#PB_Any) habe ich zwar noch nicht getestet (absichtlich) aber wenn das klappen würde wäre es erst recht komisch. warum wurde diese möglichkeit dann eingebaut, die sinnvolle individuelle freigabe aber nicht.
aber ich kann ja nicht alles einfach löschen. genau das soll mein code ja verhindern. hehe

Verfasst: 23.01.2006 20:38
von PMV
War FreeMemory(#PB_Any) nicht fehlerhaft? ... oder verwecksel ich da
was?
Selbst wenn nicht, was bringt es den ganzen Speicherplatz frei zu geben,
wenn man aber garnicht alles Freigeben möchte? Das ist in nicht wenigen
fällen Programmiertechnisch unmöglich. Z.B. benutzte ich in meiner Lib
zum größten Teil reservierten Speicher worin die IDs von Sprites und
Images gespeichert werden. Die wären mit diesem Befehl alle nicht mehr
erreichbar und somit nicht mehr aus dem Speicher entfernbar.
Ich muss also sowieso alles nacheinander sauber ablaufen damit ich jedes
Sprite/Images wieder freigeben kann wenn gewünscht. Dabei wird dann
natürlich auch der entsprechende Speicherplatz wieder frei gegeben der
nicht mehr benötigt wird. Aber nicht der gesammte speicherplatz :D

MFG PMV

Verfasst: 23.01.2006 20:43
von ts-soft
Und, hast mal im Taskmanager nachgeschaut, ob der Speicher wieder zur Verfügung steht. Ist nämlich nicht immer so.

Verfasst: 23.01.2006 20:55
von remi_meier
Hab hier ne kleine Prozedur gebastelt :)

Code: Alles auswählen

Procedure FreeStructuredString(ptrstruct, offset.l)
; offset = OffsetOf(Struct\StringField)
; ptrstruct = Pointer auf Struktur -> *pElement
  Protected p.l
  p = AllocateMemory(8)
  PokeL(p, offset)
  PokeL(p + 4, -1)
  !PUSH dword[esp+8] ; Pointer auf 'p'-Bereich
  !PUSH dword [esp+4] ; ptrstruct
	!CALL _SYS_FreeStructureStrings@8
	FreeMemory(p)
EndProcedure
Und siehe da, es läuft sauber:

Code: Alles auswählen

OpenConsole() 
Structure TestStruc 
	l.l 
	s.s 
	f.f 
EndStructure 
;*pElement.TestStruc = *pArray ;Pointer zum Speichern dem ersten Element bergeben 


Procedure FreeStructuredString(ptrstruct, offset.l)
  Protected p.l
  p = AllocateMemory(8)
  PokeL(p, offset)
  PokeL(p + 4, -1)
  !PUSH dword[esp+8] ; Pointer auf 'p'-Bereich
  !PUSH dword [esp+4] ; ptrstruct
	!CALL _SYS_FreeStructureStrings@8
	FreeMemory(p)
EndProcedure



For i = 1 To 100000 
	Elemente.l = 10 ;Anzahl der Element 
	*pArray = AllocateMemory(SizeOf(TestStruc) * Elemente) ;Speicher resevieren fr alle Elemente 
	*pElement.TestStruc = *pArray ;Pointer zum Speichern dem ersten Element bergeben 
	;Print(Str(i)) 
	For a.l = 1 To Elemente ;Elemente fllen 
		*pElement\l = Elemente + 1 - a 
		*pElement\s = "Zahl: " + Str(a) + "-------------------------------------------------------------" 
		*pElement\f = 1 / a 
		*pElement + SizeOf(TestStruc) 
	Next 
	
	*pElement = *pArray ;Erstes Element wieder auswhlen 
	For a.l = 1 To Elemente ;Elemente auslesen 
		FreeStructuredString(*pElement, OffsetOf(TestStruc\s))
		*pElement + SizeOf(TestStruc) 
	Next 
	FreeMemory(*pArray) ;Array wieder freigeben 
Next i 

For i = 1 To 100 
Delay(100) 
Next i 
CloseConsole()
Auch wenns nicht erwünscht ist, immerhin eine Lösung :freak:

greetz
Remi