Speicherleck bei Strings 3.94

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Speicherleck bei Strings 3.94

Beitrag von remi_meier »

Ausgehend von diesem Thread:
http://forums.purebasic.com/german/view ... highlight=

Wer kein AllocateMemory() für Strukturen mit Stringfeldern benutzt, muss
nicht beunruhigt sein. Es geht also um Codes wie der folgende:

Code: Alles auswählen

Structure TestStruc 
   l.l 
   s.s 
   f.f
   s2.s 
EndStructure 

*pElement.TestStruc = AllocateMemory(SizeOf(TestStruc))
*pElement\s = "hallo"
*pElement\s2 = "welt"
FreeMemory(*pElement)
; Hier entsteht ein Speicherleck: \s und \s2 werden NICHT
; von PB automatisch freigegeben! Auch ein Zuweisen eines
; Leerstrings ("") hilft nicht viel.
PB stellt also direkt keine Möglichkeit zur Verfügung um diese Strings aus
dem Speicher zu entfernen! Wenn man nun den ASM-Output liest, findet
man jedoch eine Methode :) . Dazu habe ich 2 Prozeduren gemacht:

Code: Alles auswählen

Procedure FreeStructuredString1(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 
und

Code: Alles auswählen

Procedure FreeStructuredString2(ptrstruct.l, ptroffsets.l) 
  !PUSH dword [esp+4] ; offsets der Strings
  !PUSH dword [esp+4] ; ptrstruct 
  !CALL _SYS_FreeStructureStrings@8
EndProcedure 
Zur Anwendung zwei Codebeispiele:

Code: Alles auswählen

Structure TestStruc 
   l.l 
   s.s 
   f.f
   s2.s 
EndStructure 

*pElement.TestStruc = AllocateMemory(SizeOf(TestStruc))
*pElement\s = "hallo"
*pElement\s2 = "welt"
; vor dem FreeMemory() noch die Strings freigeben.
; dazu muss die Funktion für jeden String einzeln aufgerufen
; werden:
FreeStructuredString1(*pElement, OffsetOf(TestStruc\s))
FreeStructuredString1(*pElement, OffsetOf(TestStruc\s2))
; nun sind die Strings nicht mehr benutzbar und nicht
; mehr im Speicher.
FreeMemory(*pElement)
Die Methode mit FreeStructuredString2() ist komplizierter, aber allgemeiner
oder doch auch wieder einfacher?

Code: Alles auswählen

Structure TestStruc 
   l.l 
   s.s 
   f.f
   s2.s 
EndStructure 

; Beliebig viele Offsets der Strings mit abschliessendem -1
; muss für jede Struktur gemacht werden!
DataSection
offTestStruc: 		; Label zum Zugriff
	Data.l OffsetOf(TestStruc\s), OffsetOf(TestStruc\s2), -1
; also etwa so:
; Data.l Offset1, Offset2, -1
; oder wie im Beispiel:
; Data.l 4, 12, -1
; dabei geht auch für grössere Strukturen z. B.
; Data.l Offset1, Offset2, Offset3, Offset4, ... , OffsetN, -1
EndDataSection

*pElement.TestStruc = AllocateMemory(SizeOf(TestStruc))
*pElement\s = "hallo"
*pElement\s2 = "welt"
; vor dem FreeMemory() noch die Strings freigeben.
; dazu muss die Funktion für die Struktur einmal aufgerufen
; werden. Dabei muss neben dem Pointer auf die Struktur, der
; Pointer zu unseren Offsets übergeben werden (?labelname)
FreeStructuredString2(*pElement, ?offTestStruc)
; nun sind die Strings nicht mehr benutzbar und nicht
; mehr im Speicher.
FreeMemory(*pElement)
Variante 2 kann man natürlich für beliebig viele Strukturen machen!

greetz
Remi
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Beitrag von helpy »

Hi remi,

SUPER!

Noch eine Frage (ich selbst brauch es zwar nicht, aber vielleicht ist es ja relevant für andere).

Was passiert bei verschachtelten Strukturen?

Code: Alles auswählen

Structure st1
	s1.s
	a.l
	s2.s
	b.l
EndStructure

Structure st2
	test.st1
	y.l
	s.s
EndStructure

; AllocateMemory(SizeOf(st2))
Wie würde das wohl hier aussehen?
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich denke das geht dann so:

Code: Alles auswählen

DataSection
  offst2:
    Data.l OffsetOf(st2\test\s1), OffsetOf(st2\test\s2), OffsetOf(st2\s), -1
EndDataSection
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Beitrag von helpy »

NicTheQuick hat geschrieben:Ich denke das geht dann so:

Code: Alles auswählen

DataSection
  offst2:
    Data.l OffsetOf(st2\test\s1), OffsetOf(st2\test\s2), OffsetOf(st2\s), -1
EndDataSection
Yep! Das sieht logisch aus! ... hätte wohl nur ein wenig mehr nachdenken müssen :-(
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Funktioniert hier nicht :?

Ausserdem geht es so nicht... Und ich bin auch gerade etwas zu ausgelaugt
um zu verstehen, was mir der ASM-Output sagen will:

Code: Alles auswählen

s_st1:
 dd 0
 dd 8
 dd 12
 dd 20
 dd -1
s_st2:
 dd -2, 1, 0, 24, s_st1
 dd 28
 dd -1
bei einer Struktur wie

Code: Alles auswählen

Structure st1 
   s1.s 
   a.l 
   s2.s 
   s3.s
   b.l 
   s4.s
EndStructure 

Structure st2 
   test.st1 
   y.l 
   s.s 
EndStructure
Das Problem ist die 24, die sich immer verändert wenn man an st1 was
ändert... Hab da jetzt grad keine Idee.
Sry.

Ich vermute, es würde auch so gehen (ungetestet und keine Garantie):

Code: Alles auswählen

DataSection
offsets:
Data.l OffsetOf(st2\test) + OffsetOf(st1\s1), OffsetOf(st2\test) + OffsetOf(st1\s2), OffsetOf(st2\test) + OffsetOf(st1\s3)
Data.l OffsetOf(st2\test) + OffsetOf(st1\s4), OffsetOf(st2\s), -1
EndDataSection
greetz
Remi
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Das Problem ist die 24, die sich immer verändert wenn man an st1 was
ändert... Hab da jetzt grad keine Idee.
Sry.
Ich hab zwar keine ahnung von ASM ... aber wenn ich die Speichergröße von st1 nehme dann kommt man doch auf 24. Sind ja 6 Elemente, mal 4 = 24 :D .

Oder verhält sich das anders?

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Stimmt, lol :D
Hab mich da wohl verrechnet (glaubs mir einfach^^)

Dann könnte das wohl folgendermassen aussehen:

Code: Alles auswählen

Structure st1 
   s1.s 
   a.l 
   s2.s 
   s4.s 
EndStructure 

Structure st2 
   test.st1 
   y.l 
   s.s 
EndStructure


DataSection
offst1:
Data.l OffsetOf(st1\s1), OffsetOf(st1\s2), OffsetOf(st1\s4), -1
offst2:
Data.l -2, 1, 0, SizeOf(st1), ?offst1
Data.l OffsetOf(st2\s), -1
EndStructure
Was die 1 und die 0 sollen, weiss ich allerdings nicht... Ein Risiko ist also
da.

Und es könnte auch auf Linux laufen, einfach ausprobieren, hab keins und
weiss deshalb nicht, ob da was anders läuft. Die Chancen stehen aber gut.

greetz
Remi
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Die StructureMap hab ich doch schonmal erklärt: http://forums.purebasic.com/german/view ... 49&start=0
Der Code ganz unten auf der 1. Seite dürfte alles erklären, mit der Ausnahme das ich damals nicht verschachtelte Strukturen beobachtet hab, aber das sollte ja nich so schwer sein. ;)
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Netter Code :)
Aber genau das ist ja das Problem (oder jetzt ev. auch nicht mehr). Also
die nicht verschachtelten Strukturen stehen ja schon im ersten Post, un-
sicherheit besteht nur bei verschachtelten Strukturen (obwohl das auch
durch einen kleinen Test geklärt werden könnte, wozu ich aber leider zu
faul bin).
Wenn du da Informationen hast, sind wir dir dankbar (also v. a. die 0 und
die 1 aus dem Post darüber)!

greetz
Remi
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Hm, dann hab mir den Thread wohl doch zu ungenau durchgelesen ;)
Aber ich versuch grad Fred zu erreichen, wenn ichs schaff frag ich ihn gleich ma desswegen.
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Antworten