TThread.Create erzeugt einen Stack Overflow?
Hi,
Ich bastel mal wieder mit Threads rum. folgender Code:
Delphi-Quellcode:
TConnectThread = class(TThread)
private FTCP: TIdTCPClient; FHost: String; FPort: Integer; FConnected: Boolean; public procedure Execute; override; property TCP: TIdTCPClient read FTCP write FTCP; property Host: String read FHost write FHost; property Port: Integer read FPort write FPort; property Connected: Boolean read FConnected; end; procedure TConnectThread.Execute; begin Priority:=tpLower; FConnected:=False; FTCP.Connect(FHost,FPort); FConnected:=True; end;
Delphi-Quellcode:
Wenn ich das ganze so aufrufe wird bei TConnectThread.Create eine Exception geworfen welche da lautet "Stack Overflow".
try
CT:=TConnectThread.Create(True); <-- CT.FreeOnTerminate:=True; CT.TCP:=Fidtcp; CT.Host:=Host; CT.Port:=Port; T:=GetTickCount+5000; CT.Resume; Das ganze kann man auch mit einem TThread machen, es passiert das selbe. Das ganze wird in keiner Rekursion, ja noch nichtmal in einer Schleif aufgerufen, von daher verstehe ich absolut nicht was das soll :cry: Hat da irgendwer eine idee? |
Re: TThread.Create erzeugt einen Stack Overflow?
:? push :?
|
Re: TThread.Create erzeugt einen Stack Overflow?
Moin Gereon,
ich kann das Problem weder mit D7, noch mit D2006 nachvollziehen. Wenn es wirklich am Konstruktor liegt, müsste das Problem allerdings auch bei jedem der TThread benutzt geschehen. Übrigens gehört das Setzen von Eigenschaften nicht in Execute sondern in Create, und die das, private, Feld FConnected zu in Execute zu setzen ist völlig überflüssig, wenn Du FreeOnTerminate auf true setzt. |
Re: TThread.Create erzeugt einen Stack Overflow?
Mir ist schon klar dass es nicht an TThread liegt....ich benutze im selben Programm auch noch nen anderen Thread, und der funktioniert...
Ich stehe hier echt völlig vor einer Wand. wie gesagt: es ist eigentlich nichts da was den Stack wirklich füllen könnte und trotzdem kommt ein Overflow...immer :cry: |
Re: TThread.Create erzeugt einen Stack Overflow?
Hallo Gereon,
wenn CT eine Property mit einem Setter ist, könnte der Fehler dort zu suchen sein. Möglicherweise wird die Setter-Methode rekursiv aufgerufen. Gruß Hawkeye |
Re: TThread.Create erzeugt einen Stack Overflow?
Zitat:
nein, leider nicht. CT ist eine Lokale variable. Aber jetzt kommt schon bei diesem Code eine AV:
Delphi-Quellcode:
Statt dem ganzen Thread gedöhns drumherum...
if FIdTCP.Connected then Exit;
try Fidtcp.Connect(Host,Port); Aber erst beim Connect...Die Überprüfung auf Connected geht anstandslos. Zitat:
|
Re: TThread.Create erzeugt einen Stack Overflow?
Hat dein Thread keinen Konstruktor? bzw. wie sieht der aus?
|
Re: TThread.Create erzeugt einen Stack Overflow?
Zitat:
Brauchte ich in dem Fall nicht. |
Re: TThread.Create erzeugt einen Stack Overflow?
Moin Gereon,
was passiert denn vor dieser Zeile:
Delphi-Quellcode:
Ich vermute nämlich mal, dass die Ursache des Stack-Overflow an einer ganz anderen Stelle zu suchen ist, es dauert nur eine Weile, bis der Überlauf eintritt.
CT:=TConnectThread.Create(True); <--
Auftreten kann der ja eigentlich nur durch ein nicht abbrechende Rekursion, ob die Rekursion nun absichtlich hervorgerufen wird, oder nicht. Einer der "beliebtesten" Fehler in diesem Falle: Innherhalb einer Getter-Methode einer Eigenschaft wird die Eigenschaft selber wieder gelesen. |
Re: TThread.Create erzeugt einen Stack Overflow?
Ok, also praktisch mal ein Backtrace was bis dahin passiert.
(Ich kann schonmal von vorneherein sagen: in meinem Code kommt weder eine Schleife noch eine absichtliche Rekursion vor... das mit den Gettern...nicht das es mir aufgefallen wäre) Das ganze ist extrem gekürzt... aber alles relevante sollte drin sein. So, der ButtonClick
Delphi-Quellcode:
Aufgerufen wird zunächst C.Connected:
TForm_Main = class(TForm)
public I: TChatInterface; C: TChatClient; end; procedure TForm_Main.FormCreate(Sender: TObject); begin C.OnSleep:=Application.ProcessMessages; end; procedure TForm_Main.Btn_ConnectClick(Sender: TObject); var ID: Integer; req: TChatDataPackage; begin //Wir wollten unsern Client mit einem Server Verbinden if C.Connected then //Kommt nicht vor, wir sind noch nicht Connected... else begin ID:=I.ServerHistory.Add(Cmb_Hostname.Text); // Erstmal Servername speichern try C.Connect(I.ServerHistory[ID].Host,I.ServerHistory[ID].Port); //Verbinden req :=TChatDataPackage.Create('LOGIN',I.Profile.Nick,I.Profile.Passwd); //Login-Request Erstellen C.OnUserInput(req); //und absenden req.Free; //und wieder freigeben except on E: EConnectException do I.AddServer('Connection Failed'); //Wenns schiefgeht Fehlermeldung machen end; end; I.ServerHistory.Export2Strings(Cmb_HostName.Items); //Liste mit den Servern Updaten end;
Delphi-Quellcode:
Dann I.ServerHistory.Add
TChatClient =class
private Fidtcp: TIdTCPClient; FOnSleep: TOnSleep; public procedure Connect(Host: String; Port: Integer); function Connected: Boolean; property OnSleep: TOnSleep write FOnSleep; end; procedure TChatClient.Connect(Host: String; Port: Integer); var CT: TConnectThread; T: Cardinal; TT: TThread; begin if FIdTCP.Connected then Exit; try CT:=TConnectThread.Create(True); CT.FreeOnTerminate:=True; CT.TCP:=Fidtcp; CT.Host:=Host; CT.Port:=Port; T:=GetTickCount+5000; CT.Resume; while (not CT.Terminated) do begin FOnSleep; if (T-GetTickCount<0) or (Fidtcp.Connected) then Break; Sleep(50); end; CT.Terminate; if not Fidtcp.Connected then raise EConnectException.Create(''); FListeningThread.Resume; except raise EConnectException.Create(''); end; end; function TChatClient.Connected: Boolean; begin Result:=FIdTCP.Connected; end;
Delphi-Quellcode:
Dann kommt C.Connect(I.ServerHistory[ID].Host,I.ServerHistory[ID].Port)
TChatInterface = class (TObject)
private FServerHistory: TServerHistory; public property ServerHistory: TServerHistory read FServerHistory; end; type TServer = record Name: String; Host: String; Port: Integer; end; TServers = array of TServer; TServerHistory = class(TObject) private FItems: TServers; function Cmp(V1,V2: TServer): Integer; public function Add(S: String): Integer; overload; function Add(Name,Host: String; Port: Integer): Integer; overload; procedure Export2Strings(S: TStrings); property Items[ID: Integer]: TServer read GetItem; default; end; function TServerHistory.Add(S: String): Integer; var Name,Host: String; begin //Ungeparsten Server in Liste schmeissen S:=Trim(S); if Pos('(',S)>0 then begin // "Name (Host:Port)" Name:=Copy(S,1,Pos(' (',S)-1); S:=Copy(S,Pos(' (',S)+2,Length(S)-Pos(' (',S)); end; Host:=Copy(S,1,Pos(':',S)-1); Delete(S,1,Pos(':',S)); Result:=Add(Name,Host,StrToInt(S)); end; function TServerHistory.Add(Name, Host: String; Port: Integer): Integer; var i, Akt, Hi, Lo: Integer; S: TServer; begin //Server an sortierter Position einfügen S.Name:=Name; S.Host:=Host; S.Port:=Port; Hi:=High(FItems); Lo:=Low(FItems); if Hi<0 then Hi:=0; Akt:=Abs(Hi+Lo) div 2; while Hi-Lo<2 do begin //Richtige Stelle suchen i:=Cmp(FItems[Akt],S); case i of 1: Hi:=Akt; 0: Exit; -1: Lo:=Akt; end; Akt:=(Hi+Lo) div 2; end; SetLength(FItems,Length(FItems)+1); for i:=Akt to Length(FItems)-1 do FItems[i+1]:=FItems[i]; FItems[Akt]:=S; Result:=Akt; end; der Zugriff auf I.ServerHistory und C.Connect steht ja oben schon |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz