![]() |
Problem bei TStringlist Freigabe
Hallo erstmal...
Also ich habe ein inzwischen doch umfangreiches Programm geschrieben, weswegen die Fehlersuche noch etwas schwerer wird. Für euch wahrscheinlich auch. Naja ..Also ich hab ein Problem mit dem Freigeben. Zum Aufbau: Ich ein Grundobjekt. In dem kommen wieder Instanzen von anderen objekten vor und in denen nun eine TStringlist. So ich hab nun zu jedem Objekt eine Methode geschrieben, die die (noch manuell) die zuerst mit create erstellten Objekte wieder frei gibt. Das geht auch so weit, nur bei einer Stringlist nicht. dazu mal ein Beispiel
Delphi-Quellcode:
Ich hoffe ihr könnt damit etwas anfangen, aber der Gesamte Code wäre zu groß...denke ich.
TObjekt1=class(TComponent)
Stringlist1:TStringlist; Stringlist2:TStringlist; Stringlist3:TStringlist; public procedure init; procedure makefree; end; TObjekt2=class(TForm); inhalt:TObjekt1; procedure init; procedure beenden; procedure TObjekt1.init; begin Stringlist1:=TStringlist.create; Stringlist2:=TStringlist.create; Stringlist3:=TStringlist.create; end; procedure TObjekt1.makefree; begin Stringlist1.free; Stringlist2.free; //Hier kommt die Zugriffsverletzung Stringlist3.free; end; procedure TObjekt2.init begin inhalt:=TObjekt1.create; inhalt.init; end; procedure TObjekt2.beenden; begin inhalt.makefree; inhalt.free; self.close; end; Schon mal vielen dank im voraus. mfg |
Re: Problem bei TStringlist Freigabe
Probiers mal mit
Delphi-Quellcode:
if Assigned(Stringlist) then
FreeAndNil(StringList);//Oder StringList.Free; |
Re: Problem bei TStringlist Freigabe
Zitat:
An deinem Code kann ich keinen Fehler erkennen. Es gibt die Möglichkeit, dass du erstens irgendwo anders den Speicherbereich der ersten StringList (wahrscheinlich bezieht sich die Fehlermeldung auf die Zeile über dem Cursor) überschreibst oder - zweitens - MakeFree mehrmals aufrufst, das wäre natürlich fatal. Für 1. solltest du die Bereichsprüfung aktivieren, dann kann schonmal nicht mehr so viel schiefgehen. Für 2. reicht es, wenn du einen Breakpoint auf die erste Zeile der Routine setzt und die Vermutung überprüfst. Verhindern kannst du das Problem mit ![]() [add]Pff, ich schreibe zu langsam :P . Zitat:
Delphi-Quellcode:
Das Assigned ist überflüssig, da es schon in TObject.Free überprüft wird.
FreeAndNil(StringList);
Und
Delphi-Quellcode:
wird nie funktionieren.[/quote]
// "Oder"-Teil
if Assigned(Stringlist) then StringList.Free; |
Re: Problem bei TStringlist Freigabe
Schade das von Angel4585 funktioniert nicht..es kommt immernoch "ungültige Zeigeroperation"
|
Re: Problem bei TStringlist Freigabe
Also mit Konstruktor und Destruktor da hab ich immer so meiner Probleme wann override oder sonstwas naja. Deswegen hab ich das mal so gemacht. Die Stringlisten gebe ich nirgendwo anders Frei das steht fest. Das einzige was es noch sein kann ist:
Es gibt ein DLL procedure die auf alles zugreifen kann per zeiger auf das Oberste Objekt. Diese wird immer "ONIDLE" aufgerufen aber nur wenn die Variable initialized auf TRUE steht. Bevor ich aber alles objekte wieder Freigebe und das Programm beende, dann setze ich initialized auf FALSE. Kann es das sein? |
Re: Problem bei TStringlist Freigabe
Ändert das etwas:
Delphi-Quellcode:
[...]
TObjekt1 = class(TComponent)
public Stringlist1:TStringlist; Stringlist2:TStringlist; Stringlist3:TStringlist; constructor Create(AOwner: TComponent) override; destructor Destroy override; end;
Delphi-Quellcode:
Auch noch die Create und Destroy Methoden hinzugefügt.
constructor TObjekt1.Create(AOwner: TComponent);
begin inherited Create(AOwner); Stringlist1:=TStringlist.create; Stringlist2:=TStringlist.create; Stringlist3:=TStringlist.create; end; destructor TObjekt1.Destroy; begin Stringlist1.free; Stringlist2.free; //Hier kommt die Zugriffsverletzung Stringlist3.free; inherited Destroy; end; Florian |
Re: Problem bei TStringlist Freigabe
Moin Zusammen,
nicht zu vergessen inherited beim constructor und destructor aufzurufen... ;-) |
Re: Problem bei TStringlist Freigabe
Hab mal ein Beispiel mit Create und Destroy gepostet.
Die Deklaration von TObject1 habe ich auch geändert. Vielleicht funktioniert es so. |
Re: Problem bei TStringlist Freigabe
Muss nochmal Fragen. Kann man im Konstruktor schon auf alle Variablen des Objektes Zugreifen?
|
Re: Problem bei TStringlist Freigabe
Nach inherited denke ich schon. Auf die selbstdefinierten StringListen erst nach deren Erzeugung mit Create.
Florian |
Re: Problem bei TStringlist Freigabe
Zitat:
|
Re: Problem bei TStringlist Freigabe
Ich muss nochmal etwas korrigieren.
TObject1 ist nur class, also kein nachfahre von TComponent sondern TObject Und wenn ich jetzt den constructor überschreiben will, kommt die Kompilermeldung "statische Methoden können nicht überschrieben werden" |
Re: Problem bei TStringlist Freigabe
Du musst den Konstruktor nicht überschreiben, da du ihn in 99% der Fälle über
Delphi-Quellcode:
aufrufen wirst. Dort ist ja klar erkennbar, um wlechen Konstruktor welcher Klasse es sich handelt.
TObject1.Create;
Der virtuelle Konstruktor von TComponent ist lediglich für den Form-Designer von Nöten. |
Re: Problem bei TStringlist Freigabe
Zitat:
|
Re: Problem bei TStringlist Freigabe
Vielen Dank erstmal für die schnellen antworten und die rege beteiligung. Ich komme heut leider nicht mehr zum ausprobieren..Schade
Aber trotzdem schon mal vielen Dank mfg Frank |
Re: Problem bei TStringlist Freigabe
Also ich hab das mal ausprobiert, wie ihr das beschrieben habt, es nützt nichts. Es geht immernoch nicht. Es hat nix bewirkt. Selber Fehler... :cry:
|
Re: Problem bei TStringlist Freigabe
Was für eine Meldung kommt eigentlich GENAU? Zugriffsverletzung auf Adresse 0? vielleicht hat es ja mit was ganz anderem zu tun.
|
Re: Problem bei TStringlist Freigabe
Moin Frank,
hast Du irgendwo ein (dynamisches) Array im Programm, oder arbeitest mit Pointern? Ich habe den Verdacht, dass irgendwo ein Speicherbereich überschrieben wird, der dann den Fehler verursacht. |
Re: Problem bei TStringlist Freigabe
Also es kommt als erstes "Ungültige Zeigeroperation" und zwar genau an der schon oben beschriebenen Stelle. Danach entstehen (wahrscheinlich aufgrund des Fehlers) eine Zugriffsverletzung auf einen Speicherbereich (007A7261) ... Ja hab keine Ahnung woran das liegt. Ja und ich arbeite mit dynamischen arrays und mit Pointern und mit naja kenn den Fachausdruck nicht, ich nenne es mal Pointerketten, also Listen wo ein Glied auf das andere zeigt..Ja mehr kann ich dazu leider nicht sagen ich weiß nicht ob euch 800 Code was anfangen könnt... (Ich bin erstaunt wie klein das Programm eigentlich jetzt ist, meine vorgänger Version hatte rund 6 mal so viel, wo das wohl hin is...)
:o :dancer2: :coder: Achja und weil überübermorgen Weihnachten ist , alles gute euch allen !!! :xmas: |
Re: Problem bei TStringlist Freigabe
Wo zeigen denn deine Zeiger hin?
Prüf mal ob einer deiner Zeiger aus der Kette zufällig auf die Stringlist zeigt. |
Re: Problem bei TStringlist Freigabe
Warum sollte der das tun?, Entweder zeigt er nirgendwo hin also NIL oder er zeigt auf ein Glied. Oder kann es sein das Delphi so "blöd" ist und zwei sachen den selben Zeiger gibt, das geht doch ne. Ne das kann ich mir nicht vorstellen.
|
Re: Problem bei TStringlist Freigabe
Naja man kann den Zeigern ja selber irgendwelche Adressen zuweisen, falls du das machst wärs schon möglich das du ne stringlist erwischt.In dem Fall ist aber nicht Delphi schuld, sondern du. :coder2:
|
Re: Problem bei TStringlist Freigabe
Also ich schreib doch mal den ganzen Code rein also hier ist er
Kernelunit:
Delphi-Quellcode:
Script-dll
unit Kernelunit;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, AppEvnts, typenunit,dglopengl,Inifiles; type PKernel = ^TKernel; Tfunc=procedure (data:PKernel);stdcall; PFunktionsglied=^TFunktionsglied; TFunktionsglied=record davor:PFunktionsglied; Funktion:cardinal; danach:PFunktionsglied; end; TKonsole=class private FMsgpos:integer; FBGColor:TRGBi; Fvisible:boolean; Fontsize:byte; procedure SetBGColor(BGColor:TRGBi); procedure Setmsgpos(msgpos:integer); procedure ChangeVisible(visible:boolean); public keycodes:TInifile; Script:TStringlist; Msglist:TStringlist; keyboardinput:array of word; keycount:word; Scriptpos:cardinal; maxlines:word; systemfont:cardinal; systempfad:string; befehl:string; value:Tstrarr; translatedkeyarray:string; dauer:cardinal; change:boolean; booted:boolean; port:Tviewport; constructor create(AOwner:TComponent); destructor destroy;override; property BGColor:TRGBi read FBGColor write SetBGColor; property visible:boolean read Fvisible write ChangeVisible; property msgpos:integer read fmsgpos write Setmsgpos; procedure Init(port:Tviewport); procedure MsgToBuffer(); procedure addmsg(text:string;color:TRGBi); procedure addscript(text:string); function TranslateKeyarray():string; procedure Keyinterpret(Sender: TObject; var Key: Word; Shift: TShiftState); procedure makefree; end; TOpenGL =class private fdc:Hdc; fhrc:hglrc; fviewport:TViewport; procedure Setdc(dc:hdc); procedure Sethrc(hrc:hglrc); procedure Setviewport(viewport:TViewport); public initialized:boolean; smartrenderbool:boolean; property dc:hdc read fdc write setdc; property hrc:hglrc read fhrc write sethrc; property viewport:TViewport read fviewport write Setviewport; procedure SmartInitialize(Owner:TComponent); procedure SmartRender(Owner:TComponent); procedure SmartFinalize(Owner:TComponent); procedure DestroyDC(Owner:TComponent); procedure makefree; end; TKernel = class(TForm) ApplicationEvents1: TApplicationEvents; procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean); procedure FormCreate(Sender: TObject); private Tempspeicher:Tvars;{ Private-Deklarationen } public tryclose:boolean; Konsole:TKonsole; OpenGL:TOpenGL; funcnames:TStringlist; functions:array of TFunc; deletedfunctions:array of cardinal; dyndllnames:Tstringlist; dyndlls:array of Thandle;{ Public-Deklarationen } renderfunctionskette:PFunktionsglied; procedure Initmemory(); procedure Freememory(); procedure Freedlls(); function GetMemoryVars():TVars; function Registervariable(size:Byte):cardinal; procedure Freevariable(address:cardinal); procedure Funktionsketteabarbeiten(address:PFunktionsglied); procedure freefunktionskette(address:PFunktionsglied); function Addfunktionsglied(address:PFunktionsglied;functionindex:cardinal;position:cardinal):cardinal; function Delfunktionsglied(address:PFunktionsglied;position:cardinal):boolean; function Addfunktion(dll:THandle;name:pansichar):integer; function Delfunktion(index:cardinal):boolean; procedure beenden(); end; var Kernel: TKernel; procedure interpret(data:PKernel);stdcall;external 'script.dll'; implementation {$R *.dfm} procedure TKonsole.SetBGColor(BGColor:TRGBi); begin FBGColor[0]:=BGColor[0]; FBGColor[1]:=BGColor[1]; FBGColor[2]:=BGColor[2]; end; procedure TKonsole.addmsg(text:string;color:TRGBi); begin msglist.Add(inttostr((color[0]*1000000)+(color[1]*1000)+(color[2]))+';'+text); msgpos:=msglist.Count-maxlines; end; procedure TKonsole.addscript(text:string); begin dauer:=0; script.Add(text); end; function TKonsole.TranslateKeyarray():string; var i,code:word; precode:byte; text:string; begin result:=''; text:=''; if length(keyboardinput)>0 then begin for i:=0 to length(keyboardinput)-1 do begin code:=keyboardinput[i]; precode:=code div 1000; code:=code mod 1000; case precode of 0 : begin text:=keycodes.ReadString('nothing',inttostr(code),''); end; //Nix 1 : begin text:=keycodes.ReadString('shift',inttostr(code),''); end; //Umschalt 2 : begin text:=keycodes.ReadString('alt',inttostr(code),''); end; //Alt 3 : begin text:=keycodes.ReadString('shiftalt',inttostr(code),''); end; //Alt+Umschalt 5 : begin text:=keycodes.ReadString('ctrl',inttostr(code),''); end; //Ctrl 6 : begin text:=keycodes.ReadString('shiftctrl',inttostr(code),''); end; //Umschalt+Ctrl 7 : begin text:=keycodes.ReadString('altctrl',inttostr(code),''); end; //ctrl+Alt 8 : begin text:=keycodes.ReadString('shiftaltctrl',inttostr(code),''); end; end; //Umschalt+Alt+Ctrl result:=result+text; change:=true; end; end; end; constructor TKonsole.create(AOwner:TComponent); begin inherited create; systempfad:=extractfiledir((aowner.Owner as TApplication).ExeName); Script:=Tstringlist.Create; Script.LoadFromFile(systempfad+'\startscript.txt'); Scriptpos:=0; Msglist:=TStringlist.Create; Msglist.LoadFromFile(systempfad+'\readme.txt'); keycodes:=TInifile.Create(systempfad+'\keycodes.ini'); change:=false; booted:=false; visible:=false; dauer:=0; bgcolor:=bgblue; fontsize:=20; translatedkeyarray:=''; end; procedure TKonsole.Init(port:Tviewport); begin self.port[0]:=port[0]; self.port[1]:=port[1]; self.port[2]:=port[2]; self.port[3]:=port[3]; maxlines:=port[3] div fontsize; dec(maxlines); end; procedure TKonsole.MsgToBuffer(); var line_s,color:string; line_b:array of Byte; i,j,lines:word; icolor:cardinal; r,g,b:byte; begin glcolor3f(bgcolor[0]/255,bgcolor[1]/255,bgcolor[2]/255); glbegin(gl_quads); glvertex3i(port[0],port[1],-1); glvertex3i(port[0],port[1]+port[3],-1); glvertex3i(port[0]+port[2],port[1]+port[3],-1); glvertex3i(port[0]+port[2],port[1],-1); glend; if msglist.Count>0 then begin if maxlines>(msglist.Count-msgpos) then lines:=(msglist.Count-msgpos) else lines:=maxlines; for j:=1 to lines do begin line_s:=msglist.Strings[j+msgpos-1]; color:=copy(line_s,0,ansipos(';',line_s)-1); line_s:=copy(line_s,ansipos(';',line_s)+1,length(line_s)); if color='' then glcolor3f(0.8,0.8,0.8) else begin icolor:=strtoint(color); r:=icolor div(1000000); g:=(icolor mod(1000000))div(1000); b:=icolor mod(1000); glcolor3f(1/255*r,1/255*g,1/255*b); end; glrasterpos3i(port[0],port[1]+port[3]-(fontsize*j),-1); gllistbase(systemfont); setlength(line_b,length(line_s)); if length(line_b)>80 then setlength(line_b,80); if length(line_s)>0 then for i:=1 to length(line_b) do line_b[i-1]:=ord(line_s[i]); if length(line_b)>0 then glcalllists(length(line_b),gl_unsigned_byte,line_b); end; end; glcolor3f(1,1,0); glrasterpos3i(port[0],port[1],-1); gllistbase(systemfont); line_s:=translatedkeyarray; setlength(line_b,length(line_s)); if length(line_b)>80 then setlength(line_b,80); if length(line_b)>0 then for i:=1 to length(line_b) do line_b[i-1]:=ord(line_s[i]); if length(line_b)>0 then glcalllists(length(line_b),gl_unsigned_byte,line_b); end; procedure TKonsole.Setmsgpos(msgpos:integer); begin if msgpos>(msglist.Count-maxlines) then msgpos:=msglist.Count-maxlines; if msgpos<0 then msgpos:=0; fmsgpos:=msgpos; change:=true; end; procedure TKonsole.ChangeVisible(visible:boolean); begin Fvisible:=visible; keycount:=0; setlength(keyboardinput,0); if visible then msgpos:=msglist.Count; end; procedure TKonsole.Keyinterpret(Sender:Tobject;var Key:Word;Shift:TShiftstate); var modkey:word; begin case key of 38 : if msgpos>0 then msgpos:=msgpos-1; 40 : if msgpos<msglist.Count-1 then msgpos:=msgpos+1; 8 : if high(keyboardinput)>-1 then begin setlength(keyboardinput,high(keyboardinput)); dec(keycount); translatedkeyarray:=translatekeyarray; end; 13 : begin Addmsg(translatedkeyarray,yellow); translatedkeyarray:=translatekeyarray; addscript(translatedkeyarray); keycount:=0; setlength(keyboardinput,keycount); translatedkeyarray:=translatekeyarray; end; else begin inc(keycount); setlength(keyboardinput,keycount); modkey:=key; if ssshift in shift then modkey:=modkey+1000; if ssalt in shift then modkey:=modkey+2000; if ssCtrl in shift then modkey:=modkey+5000; keyboardinput[keycount-1]:=modkey; translatedkeyarray:=translatekeyarray; end; end; end; destructor TKonsole.destroy; begin if assigned(Msglist) then msglist.Free; //?????????????????????????? if assigned(script) then script.Free; if assigned(keycodes) then keycodes.Free; inherited destroy; end; procedure TKonsole.makefree; begin end; {------------------------------------------------------------------------------} procedure TOpenGL.Setdc(dc:hdc); begin fdc:=dc; end; procedure TOpenGL.Sethrc(hrc:hglrc); begin fhrc:=hrc; end; procedure TOpenGL.Setviewport(viewport:TViewport); begin fviewport[0]:=viewport[0]; fviewport[1]:=viewport[1]; fviewport[2]:=viewport[2]; fviewport[3]:=viewport[3]; end; procedure TOpenGL.SmartInitialize(Owner:TComponent); var Font : HFONT; begin if (Owner is TKernel) then begin initialized:=true; smartrenderbool:=true; dc:=getdc((Owner as TKernel).Handle); if not InitOpenGL then begin messagedlg('Konnte OpenGL nicht initialisieren',mterror,[mbok],0); initialized:=false; end; hrc:= CreateRenderingContext(DC,[opDoubleBuffered],32,24,0,0,0,0); ActivateRenderingContext(DC,hrc); (Owner as TKernel).Konsole.systemfont:=glgenlists(256); Font:=CreateFont(16, 0, 0, 0, FW_MEDIUM, 0, 0, 0, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY, FF_DONTCARE or DEFAULT_PITCH, 'Courier New'); SelectObject (DC, Font); wglUseFontBitmaps (DC, 0, 255, (Owner as TKernel).Konsole.systemfont); DeleteObject(font); end; end; procedure TOpenGL.SmartRender(Owner:TComponent); begin if (Owner is TKernel) then begin glMatrixMode(GL_PROJECTION); glloadidentity; glviewport(0,0,(Owner as TKernel).Width,(Owner as TKernel).Height); glortho(0,(Owner as TKernel).Width,0,(Owner as TKernel).Height,-1,1); glMatrixMode(GL_MODELVIEW); glclearcolor(0,0,0,0); glclear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glloadidentity; gldisable(gl_depth_test); gldisable(gl_texture_2d); gldisable(gl_blend); gldisable(gl_alpha_test); gldisable(gl_fog); gldisable(gl_lighting); if (Owner as TKernel).Konsole.visible then begin (Owner as Tkernel).Konsole.MsgToBuffer; (Owner as Tkernel).Konsole.change:=false; end; end; end; procedure TOpenGL.SmartFinalize(Owner:TComponent); begin if (Owner is TKernel) then begin swapbuffers((Owner as TKernel).OpenGL.dc); end; end; procedure TOpengl.DestroyDC(Owner:Tcomponent); begin if Owner is TKernel then begin gldeletelists((Owner as TKernel).Konsole.systemfont,256); initialized:=false; smartrenderbool:=false; DeactivateRenderingContext; DestroyRenderingContext(hrc); ReleaseDC((Owner as TKernel).Handle,dc); end; end; procedure TOpenGL.makefree; begin end; {------------------------------------------------------------------------------} procedure TKernel.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if key=220 then konsole.visible:=not konsole.visible; if konsole.visible and Opengl.initialized then Konsole.Keyinterpret(Sender,Key,Shift); end; procedure TKernel.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean); begin if tryclose then beenden else begin Funktionsketteabarbeiten(renderfunctionskette); if Opengl.smartrenderbool then begin Opengl.SmartRender(self); Opengl.SmartFinalize(self); end; end; end; procedure TKernel.FormCreate(Sender: TObject); var port:Tviewport; begin initmemory; tryclose:=false; port[2]:=640; port[3]:=240; if (clientWidth-port[2])>0 then port[0]:=(clientWidth-port[2]) div 2 else port[0]:=0; port[1]:=100; konsole:=TKonsole.Create(self); konsole.Init(port); OpenGL:=TOpengl.Create; Opengl.SmartInitialize(self); funcnames:=TStringlist.Create; dyndllnames:=Tstringlist.Create; setlength(functions,1); setlength(deletedfunctions,0); functions[high(functions)]:=interpret; new(renderfunctionskette); renderfunctionskette^.Funktion:=high(functions); renderfunctionskette^.danach:=nil; funcnames.Add('script.dll;interpret;'); end; procedure TKernel.beenden(); begin Opengl.DestroyDC(self); Opengl.makeFree; Opengl.Free; Konsole.Free; freefunktionskette(renderfunctionskette.danach); freedlls; freememory; if assigned(funcnames) then freeandnil(funcnames); if assigned(dyndllnames) then freeandnil(dyndllnames); self.Close; end; procedure TKernel.Initmemory(); begin setlength(tempspeicher,0); end; procedure Tkernel.Freememory(); var i:integer; begin for i:=0 to high(tempspeicher) do begin if tempspeicher[i].flag>0 then begin freemem(tempspeicher[i].address,tempspeicher[i].size); finalize(tempspeicher[i]); end; end; end; function Tkernel.GetMemoryVars:Tvars; begin result:=Tempspeicher; end; procedure TKernel.Freedlls(); var i:integer; begin for i:=0 to high(dyndlls) do begin freelibrary(dyndlls[i]); end; end; function Tkernel.Registervariable(size:Byte):cardinal; var i:integer; found:boolean; begin found:=false; if High(tempspeicher)=-1 then begin setlength(tempspeicher,1); getmem(tempspeicher[0].address,size); tempspeicher[0].size:=size; tempspeicher[0].flag:=1; result:=0; end else begin for i:=0 to high(tempspeicher) do begin if Tempspeicher[i].address=nil then begin getmem(tempspeicher[i].address,size); tempspeicher[i].size:=size; tempspeicher[i].flag:=1; result:=i; break; found:=true; end; end; if not found then begin setlength(tempspeicher,length(tempspeicher)+1); getmem(tempspeicher[high(tempspeicher)].address,size); tempspeicher[high(tempspeicher)].size:=size; tempspeicher[high(tempspeicher)].flag:=1; result:=high(tempspeicher); end; end; end; procedure TKernel.Freevariable(address:cardinal); begin if address< high(tempspeicher) then begin freemem(tempspeicher[address].address,tempspeicher[address].size); tempspeicher[address].flag:=0; end; end; procedure TKernel.Funktionsketteabarbeiten(address:PFunktionsglied); begin if assigned(address) then begin functions[address^.Funktion](@self); if not (address^.danach=nil) then Funktionsketteabarbeiten(address^.danach); end; end; procedure TKernel.freeFunktionskette(address:PFunktionsglied); begin if assigned(address) then begin if not (address^.danach=nil) then Funktionsketteabarbeiten(address^.danach); dispose(address); end; end; function TKernel.Addfunktion(dll:THandle;name:PAnsichar):integer; var i:integer; begin result:=-1; if high(deletedfunctions)>-1 then begin @functions[deletedfunctions[high(deletedfunctions)]]:=getprocaddress(dll,name); result:=deletedfunctions[high(deletedfunctions)]; setlength(deletedfunctions,high(deletedfunctions)); end; if result=-1 then begin setlength(functions,length(functions)+1); setlasterror(0); @functions[high(functions)]:=getprocaddress(dll,name); i:=getlasterror; if i>0 then begin konsole.addmsg('SYSTEM-ERROR: '+syserrormessage(i),red); end; if @functions[high(functions)]=nil then setlength(functions,high(functions)) else result:=high(functions); end; end; function TKernel.Delfunktion(index:cardinal):boolean; begin result:=false; if index<length(functions) then begin setlength(deletedfunctions,length(deletedfunctions)+1); deletedfunctions[high(deletedfunctions)]:=index; result:=true; end; end; function TKernel.Addfunktionsglied(address:PFunktionsglied;functionindex:cardinal;position:cardinal):cardinal; var i:cardinal; glied:PFunktionsglied; begin for i:=0 to position-1 do begin if not (address.danach=nil) then address:=address^.danach else begin new(glied); address^.danach:=glied; glied^.Funktion:=functionindex; glied^.davor:=address; glied^.danach:=nil; result:=i; end; end; if not (address.danach=nil) then begin new(glied); glied^.danach:=address^.danach; address^.danach:=glied; glied^.Funktion:=functionindex; glied^.davor:=address; address:=glied^.danach; address^.davor:=glied; result:=position; end; end; function TKernel.Delfunktionsglied(address:PFunktionsglied;position:cardinal):boolean; var i:cardinal; glied:PFunktionsglied; auserhalb:boolean; begin result:=false; auserhalb:=false; for i:=0 to position-1 do begin if address.danach=nil then auserhalb:=true; end; if not auserhalb then begin glied:=address^.davor; glied^.danach:=address^.danach; dispose(address); end; end; end.
Delphi-Quellcode:
Typenunitlibrary Script; { Wichtiger Hinweis zur DLL-Speicherverwaltung: ShareMem muss sich in der ersten Unit der unit-Klausel der Bibliothek und des Projekts befinden (Projekt- Quelltext anzeigen), falls die DLL Prozeduren oder Funktionen exportiert, die Strings als Parameter oder Funktionsergebnisse übergeben. Das gilt für alle Strings, die von oder an die DLL übergeben werden -- sogar für diejenigen, die sich in Records und Klassen befinden. Sharemem ist die Schnittstellen-Unit zur Verwaltungs-DLL für gemeinsame Speicherzugriffe, BORLNDMM.DLL. Um die Verwendung von BORLNDMM.DLL zu vermeiden, können Sie String- Informationen als PChar- oder ShortString-Parameter übergeben. } uses SysUtils, Classes, Kernelunit, Typenunit, messages, windows, AppEvnts; {$R *.res} function Semikolontrennung(text:string):Tstrarr; var i,j:integer; begin setlength(result,1); result[0]:=text; j:=0; repeat i:=ansipos(';',result[j]); if not (i=0) then begin inc(j); setlength(result,j+1); result[j]:=result[j-1]; result[j-1]:=copy(result[j],0,i-1); result[j]:=copy(result[j],i+1,length(result[j])); end; until i=0; end; procedure load(data:PKernel); var handle:THandle; initfunc:TFunc; begin data^.Konsole.addmsg('Lade '+data^.Konsole.value[0],grey); setlength(data^.dyndlls,length(data^.dyndlls)+1); handle:=LoadLibrary(Pchar(data^.Konsole.systempfad+'/'+data^.Konsole.value[0])); if handle<>0 then begin data^.dyndlls[high(data^.dyndlls)]:=handle; @initfunc:=getprocaddress(handle,'init'); if @initfunc<>nil then begin initfunc(data); data^.dyndllnames.Add(data^.Konsole.value[0]); data^.Konsole.addmsg(data^.Konsole.value[0]+' geladen!',green); end else begin freelibrary(handle); setlength(data^.dyndlls,high(data^.dyndlls)); data^.Konsole.addmsg('Fehler aufgetreten (Init-Function nicht aufrufbar)'+data^.Konsole.value[0]+' nicht geladen!',red); end; end else begin setlength(data^.dyndlls,high(data^.dyndlls)); freelibrary(handle); data^.Konsole.addmsg('Fehler aufgetreten '+data^.Konsole.value[0]+' nicht geladen!',red); end; end; procedure include(data:PKernel); var pos,i:integer; path:ansistring; begin if high(data^.konsole.value)<1 then begin data^.Konsole.addmsg('Zu wenig Parameter',red); end else begin pos:=data^.dyndllnames.IndexOf(data^.Konsole.value[0]); if pos>-1 then begin path:=data^.Konsole.value[1]; pos:=data^.Addfunktion(data^.dyndlls[pos],@path[1]); if pos>-1 then begin data^.Konsole.addmsg(data^.Konsole.value[1]+' eingegliedert! Index: '+inttostr(pos),green); data^.funcnames.Add(data^.Konsole.value[0]+';'+data^.Konsole.value[1]); end else data^.Konsole.addmsg('Fehler beim Einbinden!'+data^.Konsole.value[1],red); end else data^.Konsole.addmsg('Unbekannte DLL!',red); end; end; procedure help(data:PKernel); var helptext:TStringlist; i:integer; begin helptext:=Tstringlist.Create; try if data^.Konsole.value[0]='' then begin helptext.LoadFromFile(data^.konsole.systempfad+'\help\default.txt'); data^.Konsole.addmsg('Hilfe',lgrey); end else begin helptext.LoadFromFile(data^.konsole.systempfad+'\help\'+data^.Konsole.value[0]+'.txt'); data^.Konsole.addmsg('Hilfe für: "'+data^.Konsole.value[0]+'"',lgrey); end; for i:=0 to helptext.Count-1 do begin data^.Konsole.addmsg('* |'+helptext.Strings[i],grey); end; except data^.Konsole.addmsg('Hilfe für nicht verfügbar!',red); end; helptext.Free; end; procedure info(data:PKernel); var i:integer; text:Tstrarr; vars:Tvars; str:string; glied:PFunktionsglied; begin if (data^.Konsole.value[0]='kernel') or (data^.Konsole.value[0]='all') then begin data^.Konsole.addmsg('-- Kernel --',dred); data^.Konsole.addmsg('-Temporärer Speicher Variabeln / Größe |*Index',lred); vars:=data^.GetMemoryVars; for i:=0 to high(vars) do if vars[i].flag>0 then data^.Konsole.addmsg('*'+inttostr(i)+' '+inttostr(integer(vars[i].address))+'~'+inttostr(integer(vars[i].address)+vars[i].size)+' |> '+inttostr(vars[i].size),lblue); data^.Konsole.addmsg('-dynamische DLLs',lred); for i:=0 to data^.dyndllnames.Count-1 do begin data^.Konsole.addmsg(data^.dyndllnames.Strings[i],lblue); end; data^.Konsole.addmsg('-Funktionen',lred); for i:=0 to data^.funcnames.Count-1 do begin text:=semikolontrennung(data^.funcnames.Strings[i]); data^.Konsole.addmsg(text[1],lblue); data^.Konsole.addmsg('+ aus '+text[0],dgrey); end; data^.Konsole.addmsg('-Zuordnungen',lred); data^.Konsole.addmsg('--Renderfunktionen',dred); glied:=data^.renderfunctionskette; repeat text:=semikolontrennung(data^.funcnames.Strings[glied^.funktion]); data^.Konsole.addmsg(text[1],lblue); glied:=glied^.danach; until glied=nil; end; if (data^.Konsole.value[0]='konsole') or (data^.Konsole.value[0]='all') then begin data^.Konsole.addmsg('-- Konsole --',dred); data^.Konsole.addmsg('-Systempfad',lred); data^.Konsole.addmsg(data^.Konsole.systempfad,lblue); data^.Konsole.addmsg('-Scriptposition/Befehl',lred); data^.Konsole.addmsg(inttostr(data^.Konsole.Scriptpos),lblue); data^.Konsole.addmsg(data^.Konsole.befehl,lblue); str:=''; for i:=0 to high(data^.Konsole.value) do str:=str+' | '+data^.Konsole.value[i]; data^.Konsole.addmsg(str,lblue); data^.Konsole.addmsg(inttostr(data^.Konsole.dauer),lblue); data^.Konsole.addmsg('-Ausgabeport (links,oben,breite,höhe)',lred); data^.Konsole.addmsg(inttostr(data^.Konsole.port[0])+' | '+inttostr(data^.Konsole.port[1])+' | '+inttostr(data^.Konsole.port[2])+' | '+inttostr(data^.Konsole.port[3]),lblue); data^.Konsole.addmsg('-Hintergrundfarbe (r,g,b)',lred); data^.Konsole.addmsg(inttostr(data^.Konsole.bgcolor[0])+' | '+inttostr(data^.Konsole.bgcolor[1])+' | '+inttostr(data^.Konsole.bgcolor[2]),lblue); end; end; procedure list(data:PKernel); var datei:TSearchrec; begin if data^.Konsole.value[0]='help' then begin if findfirst(data^.Konsole.systempfad+'\help\*.txt',faanyfile,datei)=0 then begin repeat data^.Konsole.addmsg(datei.Name,lgrey); until not (findnext(datei)=0); end; end; if data^.Konsole.value[0]='script' then begin if findfirst(data^.Konsole.systempfad+'\script\*.txt',faanyfile,datei)=0 then begin repeat data^.Konsole.addmsg(datei.Name,lgrey); until not (findnext(datei)=0); end; end; if data^.Konsole.value[0]='dll' then begin if findfirst(data^.Konsole.systempfad+'\dll\*.dll',faanyfile,datei)=0 then begin repeat data^.Konsole.addmsg(datei.Name,lgrey); until not (findnext(datei)=0); end; end; end; procedure close(data:PKernel); begin data^.Konsole.addmsg('Schließe Konsole',green); data^.Konsole.visible:=false; end; procedure open(data:PKernel); begin data^.Konsole.addmsg('Öffne Konsole',green); data^.Konsole.visible:=true; end; procedure exit(data:PKernel); begin data^.Konsole.addmsg('Beende Konsole',green); data^.tryclose:=true; end; //////////////////////////////////////////////////////////////////////////////// procedure regist(data:Pkernel); var address:integer; size:byte; begin if data^.Konsole.value[0]<>'' then begin try size:=strtoint(data^.Konsole.value[0]); if size=0 then begin data^.Konsole.addmsg('Unzulässige Größenangabe',red); end else begin address:=data^.Registervariable(strtoint(data^.Konsole.value[0])); data^.Konsole.addmsg('Variable der Größe: '+data^.Konsole.value[0]+' bei '+inttostr(address)+' erstellt',green); end; except data^.Konsole.addmsg('Unzulässige Größenangabe',red); end; end; end; procedure freevar(data:PKernel); var address:integer; begin if data^.Konsole.value[0]<>'' then begin try address:=strtoint(data^.Konsole.value[0]); data^.Freevariable(address); data^.Konsole.addmsg('Variable bei: '+inttostr(address)+' freigegeben',green); except data^.Konsole.addmsg('Unzulässige Adresse!',red); end; end; end; //////////////////////////////////////////////////////////////////////////////// procedure interpret(data:PKernel);stdcall; var command:string; done:boolean; text:TStrarr; i:integer; begin repeat done:=false; if (data^.Konsole.Scriptpos<data^.Konsole.Script.Count) and (data^.Konsole.dauer=0) then begin command:=data^.Konsole.Script.Strings[data^.Konsole.Scriptpos]; text:=semikolontrennung(command); data^.Konsole.befehl:=text[0]; if high(text)>0 then begin setlength(data^.Konsole.value,1); data^.Konsole.value[0]:=text[1]; for i:=2 to high(text)-1 do begin setlength(data^.Konsole.value,i); data^.Konsole.value[i-1]:=text[i]; end; end else begin setlength(data^.Konsole.value,1); data^.Konsole.value[0]:=''; end; if high(text)>1 then begin try data^.Konsole.dauer:=strtoint(text[high(text)]); except data^.Konsole.dauer:=1; data^.Konsole.addmsg('Keine gültige Tickangabe',red); end; end else data^.Konsole.dauer:=1; end; if data^.Konsole.Scriptpos<data^.Konsole.Script.Count then begin if data^.Konsole.befehl='load' then begin load(data); done:=true; end; if data^.Konsole.befehl='include' then begin include(data); done:=true; end; if data^.Konsole.befehl='help' then begin help(data); done:=true; end; if data^.Konsole.befehl='info' then begin info(data); done:=true; end; if data^.Konsole.befehl='list' then begin list(data); done:=true; end; if data^.Konsole.befehl='close' then begin close(data); done:=true; end; if data^.Konsole.befehl='open' then begin open(data); done:=true; end; if data^.Konsole.befehl='exit' then begin exit(data); done:=true; end; ////////////////////////////////////////////////////////////////////////// if data^.Konsole.befehl='regist' then begin regist(data); done:=true; end; if data^.Konsole.befehl='free' then begin freevar(data); done:=true; end; ////////////////////////////////////////////////////////////////////////// if not done then begin data^.Konsole.dauer:=0; data^.Konsole.addmsg('++ Error: Befehl "'+data^.Konsole.befehl+'" unbekannt ++',red); end else dec(data^.Konsole.dauer); if data^.Konsole.dauer=0 then inc(data^.Konsole.Scriptpos); end else begin data^.Konsole.befehl:=''; setlength(data^.Konsole.value,1); data^.Konsole.value[0]:=''; data^.Konsole.dauer:=1; end; until data^.Konsole.dauer>0; end; exports interpret; begin end.
Delphi-Quellcode:
So, ich hoffe das bringt ein bisschen Licht in die Sache, ich weiß wirklich nicht, woran das liegt...unit typenunit; interface type PRGBi =^TRGBi; TRGBi =array[0..2] of Byte; TRGBf =array[0..2] of single; TRGBAi =array[0..3] of Byte; TRGBAf =array[0..3] of single; Tviewport=array[0..3] of word; TStrarr=array of string[255]; TVar=record address:pointer; size:Byte; flag:Byte; end; TVars=array of TVar; const white:TRGBi=(255,255,255); black:TRGBi=(0,0,0); lgrey:TRGBi=(200,200,200); grey:TRGBi=(150,150,150); dgrey:TRGBi=(100,100,100); lred:TRGBi=(255,150,150); red:TRGBi=(255,0,0); dred:TRGBi=(100,0,0); lyellow:TRGBi=(255,255,150); yellow:TRGBi=(255,255,0); dyellow:TRGBi=(100,100,0); lgreen:TRGBi=(150,255,150); green:TRGBi=(0,255,0); dgreen:TRGBi=(0,100,0); lblue:TRGBi=(150,150,255); blue:TRGBi=(0,0,255); dblue:TRGBi=(0,0,100); bgblue:TRGBi=(10,10,50); implementation end. |
Re: Problem bei TStringlist Freigabe
Bitte helft mir, das Problem :gruebel: besteht leider immernoch. Ich weiß es ist viel Code, aber bitte bitte... :wall: :coder2:
|
Re: Problem bei TStringlist Freigabe
Hast du es schon mit aktivierter Bereichsprüfung probiert, wie ich oben geschrieben habe?
|
Re: Problem bei TStringlist Freigabe
hmm :gruebel: wie geht das genau?
|
Re: Problem bei TStringlist Freigabe
Ich hab meinen Fehler gefunden!
Schau mal, ob du was ähnliches im Code hast. Ich hatte es so:
Delphi-Quellcode:
Nu so und es geht:
SetLength(array, ZAHL);
for i:=0 to ZAHL do array[i] := ...;
Delphi-Quellcode:
Also es war vllt. nur ein Index zu wenig erzeugt... (wenn ich auch nich verstehe, warum keine AV kam) ;)
for i:=0 to Zahl do
begin SetLength(array, length(array)+1); end; Und wenn ich es nun so wie bei Methode 1 richtig machen will:
Delphi-Quellcode:
air
SetLength(array, ZAHL + 1);
|
Re: Problem bei TStringlist Freigabe
Zitat:
Du bist jetzt schon der zweite in dieser Woche, der ewig nach einem Fehler sucht, weil er sein Projekt einfach nicht richtig zum Debuggen einstellt :stupid: . @Master of Wind: Um zu schauen, ob du der dritte bist :mrgreen: : Projekt -> Optionen -> Compiler -> Bereichsprüfung Danach am Besten das ganze Projekt neu kompilieren lassen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:20 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