Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TThread.Create erzeugt einen Stack Overflow? (https://www.delphipraxis.net/87590-tthread-create-erzeugt-einen-stack-overflow.html)

glkgereon 2. Mär 2007 16:02


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:
  try
    CT:=TConnectThread.Create(True); <--
    CT.FreeOnTerminate:=True;
    CT.TCP:=Fidtcp;
    CT.Host:=Host;
    CT.Port:=Port;
    T:=GetTickCount+5000;
    CT.Resume;
Wenn ich das ganze so aufrufe wird bei TConnectThread.Create eine Exception geworfen welche da lautet "Stack Overflow".
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?

glkgereon 3. Mär 2007 16:57

Re: TThread.Create erzeugt einen Stack Overflow?
 
:? push :?

Christian Seehase 3. Mär 2007 17:39

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.

glkgereon 3. Mär 2007 17:50

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:

Hawkeye219 3. Mär 2007 18:05

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

glkgereon 3. Mär 2007 18:14

Re: TThread.Create erzeugt einen Stack Overflow?
 
Zitat:

Zitat von Hawkeye219
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

*nachguck*

nein, leider nicht. CT ist eine Lokale variable.

Aber jetzt kommt schon bei diesem Code eine AV:

Delphi-Quellcode:
  if FIdTCP.Connected then Exit;
  try
    Fidtcp.Connect(Host,Port);
Statt dem ganzen Thread gedöhns drumherum...
Aber erst beim Connect...Die Überprüfung auf Connected geht anstandslos.

Zitat:

In Projekt <abc> trat ein Problem mit folgender Meldung auf: 'access violation at 0x004061f0: write of address 0x00030060'. Prozess angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
Jetzt bin ich total verwirrt.... :gruebel:

DGL-luke 3. Mär 2007 18:54

Re: TThread.Create erzeugt einen Stack Overflow?
 
Hat dein Thread keinen Konstruktor? bzw. wie sieht der aus?

glkgereon 3. Mär 2007 19:33

Re: TThread.Create erzeugt einen Stack Overflow?
 
Zitat:

Zitat von DGL-luke
Hat dein Thread keinen Konstruktor? bzw. wie sieht der aus?

nein, ich habe den von TThread nicht überschrieben.
Brauchte ich in dem Fall nicht.

Christian Seehase 3. Mär 2007 20:16

Re: TThread.Create erzeugt einen Stack Overflow?
 
Moin Gereon,

was passiert denn vor dieser Zeile:

Delphi-Quellcode:
CT:=TConnectThread.Create(True); <--
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.
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.

glkgereon 3. Mär 2007 20:32

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:
  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;
Aufgerufen wird zunächst C.Connected:
Delphi-Quellcode:
  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;
Dann I.ServerHistory.Add
Delphi-Quellcode:
  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;
Dann kommt C.Connect(I.ServerHistory[ID].Host,I.ServerHistory[ID].Port)
der Zugriff auf I.ServerHistory und C.Connect steht ja oben schon


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:26 Uhr.
Seite 1 von 2  1 2      

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