Einzelnen Beitrag anzeigen

Benutzerbild von glkgereon
glkgereon

Registriert seit: 16. Mär 2004
2.287 Beiträge
 
#10

Re: TThread.Create erzeugt einen Stack Overflow?

  Alt 3. Mär 2007, 20:32
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
»Unlösbare Probleme sind in der Regel schwierig...«
  Mit Zitat antworten Zitat