Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Access Violation bei "end."???
MrSaint - So 16.11.03 22:10
Titel: Access Violation bei "end."???
Hi!
Ich hab hier n Programm (soll mal n Proxy-Server werden), welches mir kuriose Fehlermeldungen generiert! Ich benutz die Indy Komponenten (TIdTCPServer, TIdTCPClient TIdThreadMngrDefault) und ich bekomm bei "end." ne AccessViolation!!!!!!!!!!!!!
Also das is so: ich start mein programm, dann ruf ich ne seite im Browser auf. der schickt meinem programm auch korrekt alles zu und mein programm fängt an zu arbeiten. Dann bekommich aber ganz plötzlich hier ne AV:
Delphi-Quelltext
1: 2: 3: 4: 5:
| begin Application.Initialize; Application.CreateForm(TFrmMain, FrmMain); Application.Run; end. |
und ich weiß absolut net, was ich damit anfangen soll... wo is denn jetzt der blöde fehler? und genau die gleiche AV kommt gleich danach wieder. Und dann is sense: mein programm reagiert nemme und ich muss es per Strg+F2 aus Delphi raus abschießen... Wenn ich dann nochmal auf F9 drück und das programm nommal start, dann kommen wirklich die kuriosesten Fehlermeldungen... irgendwo im Source (auch im Indy Source) kommen auf einmal irgendwelche AVs etc. Wenn ich dann Delphi neustart und dann F9 drück, dann kommen wieder nur die 2 AVs von oben (nich die hundert anderen in den Indys). Also irgendwas geht da grande schief...
hab das Problem schon länger und bekomm es einfach nich in den Griff... Hab dann heftige Logging-Funktionen engebaut (bei jeder Procedure die aufgerufen wird werdn die ewichtigsten daten in ne datei ausgegeben) und da is mir aufgefallen, dass (ich glaub) immer diese Funktion als letzter Aufruf vor dem Nicht-mehr-reagieren meines Programms aufgerufen wurde:
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:
| procedure TTCPThread.DeleteFromList; var i:integer; ThreadWorkHelp:PThreadWork; TCPThreadInList:TTCPThread; begin tolog:='TCPThread.DeleteFromList - ID: TCPThread: '+inttostr(ThreadID)+'; AThread: '+inttostr(AThreadClient.ThreadID); Synchronize(log); i:=-1; try with ThreadWork.LockList do begin while (i<Count-1) do begin inc(i); ThreadWorkHelp:=Items[i]; TCPThreadInList:=ThreadWorkHelp.TCPThread; if TCPThreadInList.ThreadID=ThreadID then begin tolog:='TCPThread.DeleteFromList - Deleted Thread #'+inttostr(i)+'; ID: TCPThread: '+inttostr(ThreadID)+'; AThread: '+inttostr(AthreadClient.ThreadID); Synchronize(log); Delete(i); break; end; end; end; finally ThreadWork.UnlockList; end; tolog:='TCPThread.DeleteFromList - ID: TCPThread: '+inttostr(ThreadID)+'; AThread: '+inttostr(AThreadClient.ThreadID)+' DONE'; Synchronize(log); end; |
n bissl erklärung dazu: Diese Procedure löscht einen Eintrag aus der Liste ThreadWork (TThreadList). In ThreadWork sind Pointer auf das hier gespeichert:
Delphi-Quelltext
1: 2: 3: 4:
| TThreadWork=record AThread:TIdPeerThread; TCPThread:TTCPThread; end; |
nun wird da überprüft, welcher der TCPThreads aus der Liste mit dem eigenen (das ganze is ne Funktion aus ner Thread-Klasse) übereinstimmt und der Eintrag wird dann aus der Liste gelöscht.
Also das ganze Prog is Multi-thread-based...
Naja.. und ich weiß jetzt absolut nemme weiter :bawling: und hoff, dass ihr mir helfen könnt! In der DeleteFromList kann ich kein Fehler finden! Ich glaub der steigt schon bei dem "with ThreadWork.Locklist" aus... aber:
WARUM??? und warum bekomm ich dann ne AV bei "end."?????
MrSaint
Moderiert von
Tino: Code- durch Delphi-Tags ersetzt.
Delete - So 16.11.03 23:08
Die AV tritt bei Applictaion.Run auf. Da läuft was beim Initialisieren falsch.
MrSaint - So 16.11.03 23:12
beim initialisieren?!?!?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TFrmMain.FormCreate(Sender: TObject); begin HandleDisconnect:=true; TCPServer.Active:=True; ThreadWork:=TThreadList.Create; Application.OnException:=ErrorHandler; path:=extractfilepath(application.exename); if path[length(path)]<>'\' then path:=path+'\'; end; |
Was soll da falsch laufen?
MrSaint
Moderiert von
Tino: Code- durch Delphi-Tags ersetzt.
Delete - So 16.11.03 23:25
Keine Ahnung. So spontan wüede ich sagen es liegt an dieser Zeile:
Delphi-Quelltext
1:
| TCPServer.Active:=True; |
Kommentier die mal aus.
Motzi - Mo 17.11.03 10:05
Also wenn ganz am Ende des Progs irgendwelche Fehler auftreten, dann liegt das meistens daran, dass du dir den Stack zerschossen hast oder über irgendwelche Array/Speichergrenzen rausgegangen bist... bei den Compiler-Optionen gibt es eine Möglichkeit diese "Range-Exceptions" einzuschalten (weiß jetzt aber nicht genau wie die heißt), schau mal ob du die findest...
mstuebner - Mo 17.11.03 14:18
| Motzi hat folgendes geschrieben: |
| Also wenn ganz am Ende des Progs irgendwelche Fehler auftreten, dann liegt das meistens daran, dass du dir den Stack zerschossen hast oder über irgendwelche Array/Speichergrenzen rausgegangen bist... bei den Compiler-Optionen gibt es eine Möglichkeit diese "Range-Exceptions" einzuschalten (weiß jetzt aber nicht genau wie die heißt), schau mal ob du die findest... |
Wobei es wesentlich besser ist die Ursache für den Fehler zu beseitigen, als dessen Anzeige. Ein Arzt gibt Dir hoffentlich auch keine lange Hose um Deinen offenen Beinbruch zu kaschieren. :shock:
Motzi - Mo 17.11.03 14:30
Das wollte ich damit auch nicht sagen, ich wollte damit andeuten, dass er diese Option einschalten soll, damit solche Grenz-Überschreitungen schon zur Laufzeit erkannt werden und eine entsprechende Exception ausgelöst wird! Damit kann man dann die entsprechende Fehlerquelle finden und beseitigen..!
MrSaint - Mo 17.11.03 15:27
hmmm... also ich hab nun die "bereichsprüfung" angeschaltet... jetzt bekomm ich ne "External Exception C000001D". Laut
http://www.delphifaq.com/fq/q1061.shtml heißt das "STATUS_ILLEGAL_INSTRUCTION"... :?!?:
das is bei dieser Zeile:
Delphi-Quelltext
1:
| TCPClient.WriteLn(request); |
aber ich glaub die zeile is nur zufall... weil ich hab davor genau vor dieser zeile noch ein
Delphi-Quelltext
1:
| repeat until TCPClient.Connected; |
gehabt und da war der Fehler dann bei der Zeile...
Danach bekomm ich dann noch n Fehler im Indy-Source, der aber wohl mit der External Exception was zu tun hat, weil er bei einer Zeile passiert, wo er die TCPServerExecute aufruft (und das WriteLn von vorher steht in der TCPServerExecute)...
Und dann kommen wieder die beiden AVs auf das "end." und dann is wieder aus... reagiert nemme..
und ich glaub ihr habt mich irgendwie n bissl falsch verstanden! Der Fehler passiert net, wenn ich in Delphi auf F9 drückt, also wenn ich das programm start, sondern erst, wenn das Programm was zum Arbeiten (vom Browser) bekommt...
ich versteh das alles net...
MrSaint
Motzi - Mo 17.11.03 16:14
Arbeitest du irgendwo mit Pointern/dyn. alloziertem Speicher/dyn. Arrays oder ähnlichem?
MrSaint - Mo 17.11.03 16:17
jo, ne menge.... aber wenn ich net weiß, wo der fehler steckt, dann is das wie ne suche nach der stecknadel im heuhaufen! :(
MrSaint
Motzi - Mo 17.11.03 16:31
Was davo jetzt? Pointer oder dyn. Arrays oder beides? Bei dyn. Arrays hilft dir das "RangeChecking": Projekt-Optionen->Compiler->Runtime errors->Range checking (das ist die Überprüfung die ich oben gemeint hab). Bei Pointern wirds ein bisschen mühsamer... ich hatte auch schon das Problem, dass ich für einen Pointer unabsichtlich zuwenig Speicher reserviert hab und daher über die Grenzen des reservierten Speichers hinausgeschrieben hab. Dieser Fehler hat sich ebenfalls erst beim "end." bemerkbar gemacht. Check mal alle Routinen in denen du dyn. Speicher allozierst ob auch wirklich genug Speicher reserviert wird und dann schau was du so alles in diesen Speicher reinschreibst und ob sich das überhaupt ausgeht...
MrSaint - Mo 17.11.03 16:34
hmmm... also ich hab halt ne menge pointer drin... keine dyn. arrays... ich guck das dann heut noch durch...
MrSaint
barfuesser - Mo 17.11.03 17:48
| MrSaint hat folgendes geschrieben: |
hmmm... also ich hab nun die "bereichsprüfung" angeschaltet... jetzt bekomm ich ne "External Exception C000001D". Laut http://www.delphifaq.com/fq/q1061.shtml heißt das "STATUS_ILLEGAL_INSTRUCTION"... :?!?:
das is bei dieser Zeile:
Delphi-Quelltext 1:
| TCPClient.WriteLn(request); |
aber ich glaub die zeile is nur zufall... weil ich hab davor genau vor dieser zeile noch ein
Delphi-Quelltext 1:
| repeat until TCPClient.Connected; |
gehabt und da war der Fehler dann bei der Zeile... |
das deutet darauf hin, daß der Fehler eventuell in der vorhergehenden Zeile zu suchen ist (oder nicht der Fehler sondern der Crash), da bei Delphi Exceptions oftmals erst in der Folgezeile angezeigt werden.
Wie lautet denn die benannte Zeile?
barfuesser
MrSaint - Mo 17.11.03 17:58
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: 41: 42:
| if not exists then begin TCPClient:=TIdTCPClient.Create(Self); TCPClient.Host:=server; TCPClient.Port:=Port;
TCPThread:=TTCPThread.Create(True); TCPThread.FreeOnTerminate:=true; TCPThread.TCPClient:=TCPClient; TCPThread.AThreadClient:=AThread;
GetMem(ThreadWorkHelp,sizeof(TThreadWork)); ThreadWorkHelp.AThread:=AThread; ThreadWorkHelp.TCPThread:=TCPThread; try with ThreadWork.Locklist do begin Add(ThreadWorkHelp); log('Created new thread #'+inttostr(Count-1)); end; finally ThreadWork.UnlockList; end;
TCPThread.Resume; end else begin TCPThread:=ThreadWorkHelp.TCPThread; TCPClient:=TCPThread.TCPClient; end;
log('REQUEST: '+url+' ['+server+':'+inttostr(Port)+']');
if not TCPClient.Connected then begin TCPClient.Connect; end; TCPClient.WriteLn(request); end; |
exists ist true, wenn der Thread schon existiert. wenn so, dann wird auch der existierende TCPThread und TCPClient genutzt, ansonsten werden die beiden neu erzeugt...
also in der Zeile davor ist ein "TCPCLient.Connect;"... das fällt aber wohl net in meinen "Zuständigkeitsbereich", das sollte Indy machen... und ich glaub net, dass da so ein massiver bug drin is...
MrSaint
barfuesser - Mo 17.11.03 18:08
Falls TCPThread schon auf einen laufenden Thread verweist, dann weistTCPThread:=ThreadWorkHelp.TCPThread;diesem Zeiger einen neuen Thread zu. Keine Ahnung ob so etwas überhaupt funktionieren kann, aber ich halte dies zumindest für äußerst gewagt.
barfuesser
MrSaint - Mo 17.11.03 18:14
TCPThread is ne lokale Variable, die immer gesetzt werden muss (das da oben is n Auszug aus der TCPServerExecute)... ich muss TCPThread setzen, damit ich auf den Thread zugreifen kann (auch wenn der schon im Hintergrund läuft)... und in einer schleife vorher setz ich das ThreadWorkHelp, falls der Thread schon existiert => TCPThread:=ThreadWorkHelp.TCPThread macht den Thread, der im Hintergrund schon laüft und dessen Pointer in ThreadWorkHelp.TCPThread steckt nur für diese procedure (TCPServerExecute) zugänglich...
MrSaint
barfuesser - Mo 17.11.03 18:19
Also exists heißt dann nicht TCPThread existiert sondern ThreadWorkHelp.TCPThread existiert? Ist das so richtig?
barfuesser
MrSaint - Mo 17.11.03 18:28
ich hätt vielleicht gleich den code von der ganzen procedure posten sollen:
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: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114:
| procedure TFrmMain.TCPServerExecute(AThread: TIdPeerThread); var buf:TStrings; server,url,request,hlp:string; port,r,i:integer; TCPClient:TIdTCPClient; TCPThread:TTCPThread; ThreadWorkHelp:PThreadWork; exists:boolean; List:TList; begin if AThread.Terminated or (not AThread.Connection.Connected) then exit; log('TCPServer.Execute'); buf:=TStringList.Create; request:=''; AThread.Connection.ReadStrings(buf,1); repeat request:=request+buf[0]+#13+#10; buf.Clear; AThread.Connection.ReadStrings(buf,1); until length(buf[0])=0; request:=request+#13+#10+#13+#10; buf.Free; url:=copy(request,pos(' ',request)+1,length(request)); url:=copy(url,0,pos(' ',url)-1); if lowercase(copy(url,0,7))<>'http://' then begin send_error(AThread,'<b>PROXY ERROR:</b> Es wird nur das HTTP Protokoll unterstützt!'); AThread.Connection.Disconnect; exit; end; server:=copy(url,8,length(url)); if pos('/',server)<>0 then server:=copy(server,0,pos('/',server)-1); if pos(':',server)<>0 then begin hlp:=copy(server,pos(':',server)+1,length(server)); val(hlp,port,r); log('Port: '+hlp); if r<>0 then begin send_error(AThread,'<b>PROXY ERROR:</b> Port-Fehler!'); AThread.Connection.Disconnect; exit; end; server:=copy(server,0,pos(':',server)-1); end else port:=80; if not IsIPAddr(server) then server:=GetIPFromHost(server);
exists:=false; i:=-1; try with ThreadWork.LockList do begin while (i<Count-1) do begin inc(i); ThreadWorkHelp:=Items[i]; if ThreadWorkHelp.AThread=AThread then begin log('Reusing Thread #'+inttostr(i)); exists:=true; break; end; end; end; finally ThreadWork.UnlockList; end;
if not exists then begin TCPClient:=TIdTCPClient.Create(Self); TCPClient.Host:=server; TCPClient.Port:=Port;
TCPThread:=TTCPThread.Create(True); TCPThread.FreeOnTerminate:=true; TCPThread.TCPClient:=TCPClient; TCPThread.AThreadClient:=AThread;
GetMem(ThreadWorkHelp,sizeof(TThreadWork)); ThreadWorkHelp.AThread:=AThread; ThreadWorkHelp.TCPThread:=TCPThread; try with ThreadWork.Locklist do begin Add(ThreadWorkHelp); log('Created new thread #'+inttostr(Count-1)); end; finally ThreadWork.UnlockList; end;
TCPThread.Resume; end else begin TCPThread:=ThreadWorkHelp.TCPThread; TCPClient:=TCPThread.TCPClient; end;
log('REQUEST: '+url+' ['+server+':'+inttostr(Port)+']');
if not TCPClient.Connected then begin TCPClient.Connect; end; TCPClient.WriteLn(request); end; |
(den teil von "HIER UNINTERESSANT" bis "HIER WIRDS WIEDER INTERESSANNT" könnt ihr überspringen... da wird nur der request vom browser auseinanderklamausert...)
Also exists bedeuted, dass der AThread (der ja der Proceudre TCPServerExecute von indy her übergeben wir) existiert....
mein Porgramm acht das so:
Browser ==> TCPServer (AThread) -> TCPClient (TCPThread) ==> Webserver
und in der Funktion TCPServerExecute hab ich ja erst mal bloß das AThread gegeben. also guck ich, ob solch ein AThread schon in meiner Liste is. Wenn ja weiß ich, dass der AThread schon existiert und dann auch ein dazugehöriger TCPThread (es komm immer 1 TCPThread auf 1 AThread). Den weis ich dann zu. Und dieser TCPThread hat ne property "TCPClient" in der der Pointer für den zugehörigen TCPClient hält. Den weis ich dann auch noch zu und dann wird die Message (request) gesendet....
MrSaint
P.S.: sorry, dass ich mich hier a bissl blöd angestellt hab mit dem posten... hätte gleich die ganze procedure posten sollen :oops:
Motzi - Mo 17.11.03 21:06
Und der Fehler tritt nur auf wenn diese Routine durchlaufen wird..? Wie ist TThreadWork deklariert?
MrSaint - Mo 17.11.03 21:19
Titel: Re: Access Violation bei "end."???
| MrSaint hat folgendes geschrieben: |
Delphi-Quelltext 1: 2: 3: 4:
| TThreadWork=record AThread:TIdPeerThread; TCPThread:TTCPThread; end; |
|
Ja, also es passiert zumindest net, wenn ich das programm einfach nur starte... und wenn ich dann ne seite im browser aufruf (mein programm also daten an den TCPServer geschickt bekommt, dann wird die Methode aufgerufen, ja! da das alles multi-threaded is eiß ich eben net genau ob da der fehler liegt, aber wie ich ja schon geschrieben hab: der debugger packt mich da bei der External Exception hin! Für das durchgucken wegen dem "über den Speicherbereich rausschreiben" muss ich noch gucken, aber eigentlich kann ich's mir net vorstellen... ich reservier eigentlich bloß einmal per hand speicher und das is, wenn ich n neuen eintrag in die ThreadWork reinschreib.. und das mach ich so, wie oben in dem Quelltext drin steht (da mit dem GetMem)... das is alles...
Moment! mir kommt da gerade ein Gedanke! wenn ich den Speicher per GetMem reservier sollte ich den Speicher doch, wenn ich den eintrag aus der liste rauslösche auch wieder freigeben, oder? :idea: Ich test das mal...
MrSaint
Motzi - Mo 17.11.03 21:33
Also freigeben sollte man ihn schon, aber eigentliche Fehlerursache dürfte das nicht sein (wenn das wirklich das einzige ist wo du dyn. Speicher reservierst)...
Was ist TTCPThread für eine Klasse? Von dir oder von den Indys? (bin in Internet/Netzwerk-Programmierung nicht so bewandert). Wenn es eine Klasse von dir ist, wie schaut diese aus (Code)..?
BTW: was ist/macht das ganze eigentlich?
MrSaint - Mo 17.11.03 22:09
hmmm... also ich hab nun n freemem an entsprechender stelle drin, haat aber net wirklich was gebracht :(
TTCPThread is ne Klasse von mir, die von TThread abgeleited is. Das ganze soll mal ein ProxyServer werden. Dazu brauch ich ein TidTCPServer, der die Verbindungen Browser <-> Mein Programm. Dann brauch ich noch nen TIdTCPClient der die Verbindung Mein Programm <-> Webserver.
Wenn der Browser also ne anfrage schickt springt mein TCPServer ein. Da wird dann die Procedue OnExecute aufgerufen. Die klamausert bei mir dann die daten aauseinander und "bestückt" einen TCPClient damit... so weit so gut.
wenn jetzt der Webserver antwortet, muss mein TCPClient einspringen. Da gibts aber kein Ereignis dazu (OnServerWrite oder sowas), also muss man das mit nem Thread abfangen. Das macht mein TTCPThread. und da gibts dann für jede Instanz von TCPClient einen TCPThread der dann immer diese Verbindung auf neue Nachrichten überprüft. und wie schon gesagt gibts für jeden Thread vom TCPServer (Verbindung Browser <-> mein Programm) (das is der AThread) einen TCPThread und einen TCPClient.
jetzt poste ich hier mal die unit "thread.pas", die bei mir den kompletten TTCPThread beinhaltet (is nun nich auskommentiert und auch nich "schöngemacht [ also auskommentierte Linien entfernt etc.] ).
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: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207:
| unit thread;
interface
uses Classes, IdTCPClient, IdTCPServer;
type TTCPThread = class (TThread) private Buf:array [1..10240] of byte; BufSize,SizeToWrite:int64; FTCPClient:TIdTCPClient; FAThreadClient:TIdPeerThread; tolog:string; TerminateOK:boolean; DisconnectOK: boolean; procedure HandleInput; procedure log; procedure DeleteFromList; procedure TCPThreadTerminate(Sender:TObject); procedure TCPClientDisconnect(Sender:TObject); protected procedure Execute; override; published property AThreadClient: TIdPeerThread read FAThreadClient write FAThreadClient; property TCPClient:TIdTCPClient read FTCPClient write FTCPClient; procedure EndWork; end;
implementation
uses mainFrm, SysUtils;
function ArrToStr(arr: array of byte;high:integer):string; var i:integer; begin result:=''; i:=-1; while (i<high) do begin inc(i); result:=result+chr(arr[i]); end; end;
procedure TTCPThread.Execute; begin TerminateOK:=false; DisconnectOK:=false; OnTerminate:=TCPThreadTerminate; FTCPClient.OnDisconnected:=TCPClientDisconnect; tolog:='New Thread ID: TCPThread: '+inttostr(ThreadID)+'; AThread: '+inttostr(AthreadClient.ThreadID); Synchronize(log); while not Terminated do begin if not FTCPClient.Connected then begin EndWork; end else begin try FTCPClient.ReadBuffer(buf,1); BufSize:=FTCPClient.InputBuffer.Size; SizeToWrite:=1; synchronize(HandleInput); if BufSize>0 then begin if BufSize>10240 then begin SizeToWrite:=10240; repeat FTCPClient.ReadBuffer(Buf,10240); Dec(BufSize,10240); Synchronize(HandleInput); until BufSize<10240; if BufSize>0 then begin SizeToWrite:=BufSize; FTCPClient.ReadBuffer(Buf,BufSize); BufSize:=0; Synchronize(HandleInput); end; end else begin SizeToWrite:=BufSize; FTCPClient.ReadBuffer(Buf,BufSize); BufSize:=0; Synchronize(HandleInput); end; end else SizeToWrite:=0; except end; end; end; end;
procedure TTCPThread.log; begin FrmMain.log(tolog); end;
procedure TTCPThread.HandleInput; begin if SizeToWrite=0 then exit; AThreadClient.Connection.WriteBuffer(Buf,SizeToWrite); end;
procedure TTCPThread.DeleteFromList; var i:integer; ThreadWorkHelp:PThreadWork; TCPThreadInList:TTCPThread; begin tolog:='TCPThread.DeleteFromList - ID: TCPThread: '+inttostr(ThreadID)+'; AThread: '+inttostr(AThreadClient.ThreadID); Synchronize(log); i:=-1; try with ThreadWork.LockList do begin while (i<Count-1) do begin inc(i); ThreadWorkHelp:=Items[i]; TCPThreadInList:=ThreadWorkHelp.TCPThread; if TCPThreadInList.ThreadID=ThreadID then begin tolog:='TCPThread.DeleteFromList - Deleted Thread #'+inttostr(i)+'; ID: TCPThread: '+inttostr(ThreadID)+'; AThread: '+inttostr(AthreadClient.ThreadID); Synchronize(log); FreeMem(ThreadWorkHelp); Delete(i); break; end else begin end; end; end; finally ThreadWork.UnlockList; end; tolog:='TCPThread.DeleteFromList - ID: TCPThread: '+inttostr(ThreadID)+'; AThread: '+inttostr(AThreadClient.ThreadID)+' DONE'; Synchronize(log); end;
procedure TTCPThread.EndWork; begin tolog:='TCPThread.EndWork - ID: TCPThread: '+inttostr(ThreadID)+'; AThread: '+inttostr(AthreadClient.ThreadID); Synchronize(log); try DeleteFromList; except end; try FTCPClient.Free;
except end; TerminateOK:=true; Terminate; end;
procedure TTCPThread.TCPThreadTerminate(Sender:TObject); begin if not TerminateOK then EndWork; end;
procedure TTCPThread.TCPClientDisconnect(Sender:TObject); begin tolog:='TCPClient.Disconnect - ID: TCPThread: '+inttostr(ThreadID); synchronize(log); try AThreadClient.Connection.Disconnect; except end; end;
end. |
Ich hoff, dass das irgendwas hilft...
hab nun bald den kompletten source hier gepostet.-.. könnte demnächst eigentlich auch den ganzen Project-Source ins Netz stellen ;)
MrSaint
Motzi - Mo 17.11.03 23:47
Ich hab mir das mal angeschaut und zum besseren Verständnis auch gleich mal an meinen Stil angepasst.. ;)
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: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218:
| unit thread;
interface
uses Classes, IdTCPClient, IdTCPServer;
const MAX_COUNT = 10240;
type TTCPThread = class (TThread) private Buf: array [1..MAX_COUNT] of Byte; SizeToWrite: Int64; FTCPClient: TIdTCPClient; FAThreadClient: TIdPeerThread; ToLog: String; TerminateOK: Boolean; DisconnectOK: Boolean; procedure HandleInput; procedure log; procedure DeleteFromList; procedure TCPThreadTerminate(Sender: TObject); procedure TCPClientDisconnect(Sender: TObject); protected procedure Execute; override; published property AThreadClient: TIdPeerThread read FAThreadClient write FAThreadClient; property TCPClient:TIdTCPClient read FTCPClient write FTCPClient; procedure EndWork; end;
implementation
uses mainFrm, SysUtils;
function ArrToStr(arr: array of byte; high: Integer): String; var i: Integer; begin Result := ''; i := -1; while (i < high) do begin inc(i); Result := Result + Chr(arr[i]); end; end;
procedure TTCPThread.Execute; var BufSize: Int64; begin TerminateOK := False; DisconnectOK := False; OnTerminate := TCPThreadTerminate; FTCPClient.OnDisconnected := TCPClientDisconnect; ToLog := 'New Thread ID: TCPThread: ' + IntToStr(ThreadID) + '; AThread: ' + IntToStr(AthreadClient.ThreadID); Synchronize(log);
while not Terminated do begin if not FTCPClient.Connected then begin Terminate; end else begin try FTCPClient.ReadBuffer(Buf, 1); BufSize := FTCPClient.InputBuffer.Size; SizeToWrite := 1; Synchronize(HandleInput);
SizeToWrite := 0; if BufSize > 0 then begin if BufSize > MAX_COUNT then begin SizeToWrite := MAX_COUNT; repeat FTCPClient.ReadBuffer(Buf, MAX_COUNT); Dec(BufSize, MAX_COUNT); Synchronize(HandleInput); until BufSize < MAX_COUNT; end;
if BufSize > 0 then begin SizeToWrite := BufSize; FTCPClient.ReadBuffer(Buf, BufSize); BufSize := 0; Synchronize(HandleInput); end; end; except end; end; end; end;
procedure TTCPThread.log; begin FrmMain.log(ToLog); end;
procedure TTCPThread.HandleInput; begin if SizeToWrite <> 0 then AThreadClient.Connection.WriteBuffer(Buf, SizeToWrite); end;
procedure TTCPThread.DeleteFromList; var i: Integer; ThreadWorkHelp: PThreadWork; TCPThreadInList: TTCPThread; begin ToLog := 'TCPThread.DeleteFromList - ID: TCPThread: ' + IntToStr(ThreadID) + '; AThread: ' + IntToStr(AThreadClient.ThreadID); Synchronize(log);
i := -1; try with ThreadWork.LockList do begin while (i < Count-1) do begin Inc(i); ThreadWorkHelp := Items[i]; TCPThreadInList := ThreadWorkHelp.TCPThread; if TCPThreadInList.ThreadID = ThreadID then begin ToLog := 'TCPThread.DeleteFromList - Deleted Thread #' + IntToStr(i) + '; ID: TCPThread: '+ IntToStr(ThreadID) + '; AThread: ' + IntToStr(AthreadClient.ThreadID); Synchronize(log); FreeMem(ThreadWorkHelp); Delete(i); break; end else begin end; end; end; finally ThreadWork.UnlockList; end; ToLog := 'TCPThread.DeleteFromList - ID: TCPThread: ' + IntToStr(ThreadID) + '; AThread: ' + IntToStr(AThreadClient.ThreadID) + ' DONE'; Synchronize(log); end;
procedure TTCPThread.EndWork; begin ToLog := 'TCPThread.EndWork - ID: TCPThread: ' + IntToStr(ThreadID) + '; AThread: ' + IntToStr(AthreadClient.ThreadID); Synchronize(log); try DeleteFromList; except end; try FTCPClient.Free;
except end; TerminateOK := True; Terminate; end;
procedure TTCPThread.TCPThreadTerminate(Sender:TObject); begin if not TerminateOK then EndWork; end;
procedure TTCPThread.TCPClientDisconnect(Sender:TObject); begin ToLog := 'TCPClient.Disconnect - ID: TCPThread: ' + IntToStr(ThreadID); Synchronize(log); try AThreadClient.Connection.Disconnect; except end; end;
end. |
Hab ein paar Sachen ein bisschen geändert/optimiert, aber ob es wirklich was gebracht hat weiß ich nicht... aber nachdem du ja eh alles mitlogst.. wie schaut den nun die Ausgabe in so einer Log-Datei aus? Vielleicht kann man daraus Rückschlüsse ziehen...
MrSaint - Di 18.11.03 15:20
hmmmm... äußerst komisch... hab zuerst deinen code hier bei mir reingepackt (von der unit) und dann ausgeführt... wegen fehler / AV hat sich nix gebessert... aber dann hab ich delphi neugestartet und nochmal probiert (wegen logdatei) und da hab ich jetzt gar keinen Fehler bekommen, mein Programm is aber trotzdem "eingefroren".... hab jetzt leider keine zeit, nach dem grund zu suchen, warum da jetzt kein fehler kam, weil ich gleich wieder weg muss.... hier aber mal die log-datei:
| LOG hat folgendes geschrieben: |
14:16:01 TCPServer.Execute
14:16:02 Created new thread #0
14:16:02 REQUEST: http://www.delphi-forum.de/ [217.160.166.23:80]
14:16:02 New Thread ID: TCPThread: 4294071443; AThread: 4294073091
14:16:02 TCPServer.Execute
14:16:04 TCPClient.Disconnect - ID: TCPThread: 4294071443
14:16:04 TCPThread.EndWork - ID: TCPThread: 4294071443; AThread: 4294073091
14:16:04 TCPThread.DeleteFromList - ID: TCPThread: 4294071443; AThread: 4294073091
14:16:04 TCPThread.DeleteFromList - Deleted Thread #0; ID: TCPThread: 4294071443; AThread: 4294073091
14:16:04 TCPThread.DeleteFromList - ID: TCPThread: 4294071443; AThread: 4294073091 DONE
14:16:04 TCPServer.Disconnect
14:16:04 TCPServer.Disconnect - ThreadWork empty!
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 Created new thread #0
14:16:04 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-02.gif [217.160.166.23:80]
14:16:04 Created new thread #1
14:16:04 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-03.gif [217.160.166.23:80]
14:16:04 Created new thread #2
14:16:04 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-04.gif [217.160.166.23:80]
14:16:04 Created new thread #3
14:16:04 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-05.gif [217.160.166.23:80]
14:16:04 Created new thread #4
14:16:04 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-09.gif [217.160.166.23:80]
14:16:04 Created new thread #5
14:16:04 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-10.gif [217.160.166.23:80]
14:16:04 Created new thread #6
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-14.gif [217.160.166.23:80]
14:16:04 Created new thread #7
14:16:04 TCPServer.Execute
14:16:04 TCPServer.Execute
14:16:04 Created new thread #8
14:16:05 TCPServer.Execute
14:16:05 TCPServer.Execute
14:16:05 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-01.gif [217.160.166.23:80]
14:16:05 New Thread ID: TCPThread: 4217591655; AThread: 4217669219
14:16:05 New Thread ID: TCPThread: 4217590351; AThread: 4217667811
14:16:05 TCPServer.Execute
14:16:05 New Thread ID: TCPThread: 4217590995; AThread: 4217668531
14:16:05 New Thread ID: TCPThread: 4217589691; AThread: 4217683459
14:16:05 New Thread ID: TCPThread: 4217589047; AThread: 4217682723
14:16:05 New Thread ID: TCPThread: 4217588387; AThread: 4217681987
14:16:05 New Thread ID: TCPThread: 4217587727; AThread: 4217681267
14:16:05 New Thread ID: TCPThread: 4217587051; AThread: 4217670427
14:16:05 New Thread ID: TCPThread: 4217586407; AThread: 4217669783
14:16:04 TCPServer.Execute
14:16:04 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-27.gif [217.160.166.23:80]
14:16:05 Created new thread #9
14:16:05 TCPServer.Execute
14:16:05 TCPServer.Disconnect
14:16:05 TCPServer.Execute
14:16:05 TCPServer.Disconnect
14:16:05 TCPServer.Disconnect
14:16:05 TCPServer.Disconnect
14:16:05 TCPServer.Execute
14:16:05 TCPServer.Execute
14:16:05 REQUEST: http://www.delphi-forum.de/graphics/slices/slice-11.gif [217.160.166.23:80]
14:16:06 New Thread ID: TCPThread: 4217599323; AThread: 4217585671
14:16:06 TCPClient.Disconnect - ID: TCPThread: 4217591655
14:16:06 TCPClient.Disconnect - ID: TCPThread: 4217590351
14:16:06 TCPClient.Disconnect - ID: TCPThread: 4217589691
14:16:06 TCPClient.Disconnect - ID: TCPThread: 4217589047
14:16:05 TCPServer.Execute
14:16:06 TCPClient.Disconnect - ID: TCPThread: 4217588387
14:16:05 TCPServer.Execute
14:16:06 TCPClient.Disconnect - ID: TCPThread: 4217590995
14:16:06 TCPServer.Disconnect - Client-Disconnect Thread #0; ID: TCPThread: 4217591655; AThread: 4217669219
14:16:06 TCPServer.Disconnect
14:16:06 TCPServer.Disconnect
14:16:06 TCPClient.Disconnect - ID: TCPThread: 4217587727
14:16:06 TCPThread.EndWork - ID: TCPThread: 4217590995; AThread: 4217668531
14:16:06 TCPThread.DeleteFromList - ID: TCPThread: 4217590995; AThread: 4217668531
|
...Aber es wurde wieder die DeleteFromList als letztes aufgerufen.... irgendwie is das alles sehr verwirrend :eyecrazy:
MrSaint
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!