Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?? (https://www.delphipraxis.net/133983-stack-ueberlauf-beim-eruezgen-der-eigenen-klasse-wieso.html)

SimStar001 13. Mai 2009 10:46


Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso??
 
Hallo, ich habe folgende Klasse deklariert:

Delphi-Quellcode:
unit Livetrack;

interface

uses IdFTP, IdHTTP;

type TFTP = class(TIDFTP)
    end;

type THTTP = class(TIDHTTP)
    end;

type TLivetrack = class(TObject)
      private
      {private Vars}
      FHTTP : THTTP;
      FFTP : TFTP;
      FCacheDirectory : string;
      FFTPHost : String;
      FFTPDirectory : String;
      FFTPLoginName : String;
      FFTPPassword : String;
      FHTTPUrl : String;
      FFileName : String;
      FVID : String;

      {Set Procedures}
      procedure SetFTPHost(Host : String);
      procedure SetFTPDirectory(Directory : String);
      procedure SetFTPLoginName(LoginName : String);
      procedure SetFTPPassword(Password : String);
      procedure SetVID(VID : String);

      {get Functions}
      function GetFTPHost : String;
      function GetFTPLoginName : String;
      function GetFTPPassword : String;

      public
      {Functions}
      constructor create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String; const VID : string); overload;
      constructor create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String); overload;
      destructor destroy ; override;

      {properties}
      property CacheDirectory : String read FCacheDirectory write FCacheDirectory;
      property FTPHost : String read GetFTPHost write SetFTPHost;
      property FTPDirectory : String read FFTPDirectory write SetFTPDirectory;
      property FTPLoginName : String read GetFTPLoginName write SetFTPLoginName;
      property FTPPassword : String read GetFTPPassword write SetFTPPassword;
      property HTTPUrl : String read FHTTPUrl write FHTTPUrl;
      property FileName : String read FFileName write FFileName;
      property VID : String read FVID write SetVID;
      end;

implementation

{Set Procedures}

procedure TLivetrack.SetFTPHost(Host : String);
begin
  self.FFTP.Host := Host;
end;

procedure TLivetrack.SetFTPDirectory(Directory : String);
begin
  if Directory = '' then
    exit;
   
  if self.FFTP.Connected then
    self.FFTP.ChangeDir(Directory);
end;

procedure TLivetrack.SetFTPLoginName(LoginName : String);
begin
  if self.FFTP.Connected then
    exit;

  self.FFTP.Username := LoginName;
end;

procedure TLivetrack.SetFTPPassword(Password : String);
begin
  if self.FFTP.Connected then
    exit;

  self.FFTP.Password := Password;
end;

procedure TLivetrack.SetVID(VID : String);
begin
  self.VID := VID;
end;
// Ende Set Procedures

////////////////////////////////////////////////////////////////////////////////


{Get Functions}

function TLivetrack.GetFTPHost : String;
begin
  result := self.FFTP.Host;
end;

function TLivetrack.GetFTPLoginName : String;
begin
  result := self.FFTP.Username;
end;

function TLivetrack.GetFTPPassword : String;
begin
  result := self.FFTP.Password;
end;
// Ende Get Functions

////////////////////////////////////////////////////////////////////////////////


{Constructor}

constructor TLivetrack.create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String);
begin
  inherited create;

  self.FFTP := TFTP.Create(nil);
  self.FHTTP := THTTP.Create(nil);

  // Setzen der Parameter für HTTP und FTP
  self.CacheDirectory := CacheDirectory;
  self.FTPHost := FTPHost;
  self.FTPDirectory := FTPDirectory;
  self.FTPLoginName := FTPLoginName;
  self.FTPPassword := FTPPassword;
  self.HTTPUrl := HTTPUrl;
  self.FileName := FileName;
  //self.VID := 'none';

end;

constructor TLivetrack.create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String; const VID : string);
begin
  inherited create;

  self.FFTP := TFTP.Create(nil);
  self.FHTTP := THTTP.Create(nil);

  // Setzen der Parameter für HTTP und FTP
  self.CacheDirectory := CacheDirectory;
  self.FTPHost := FTPHost;
  self.FTPDirectory := FTPDirectory;
  self.FTPLoginName := FTPLoginName;
  self.FTPPassword := FTPPassword;
  self.HTTPUrl := HTTPUrl;
  self.FileName := FileName;
  //self.VID := VID;

end;
// Ende Constructor

////////////////////////////////////////////////////////////////////////////////


{Destructor}

destructor TLivetrack.destroy;
begin
  self.FFTP.Free;
  self.FHTTP.free;

  inherited destroy;
end;
// Ende Destructor

////////////////////////////////////////////////////////////////////////////////

end.

Nun habe ich das Problem, dass es zu einem Stack Überlauf kommt wenn ich diese erzeugen will, allerdings nur wenn ich die Property VID aufrufe.

Delphi-Quellcode:
property VID : String read FVID write SetVID;

Der Aufruf sieht so aus :

Delphi-Quellcode:
type TForm1 = class(TForm)
   (...)
   public
    Livetrack : TLivetrack;
    { Public-Deklarationen }
  end;

(...)

Livetrack := TLivetrack.create(extractfilepath(paramstr(0)) + '\Data\Cache','marcos-ivao-tools.net'
  ,'***','***','***','***','data.csv');

Hat wer ne Idee, wieso es gerade beim Aufrufen von VID zum Überlauf kommt?

mkinzler 13. Mai 2009 10:48

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Ja der Setter rufst sich ja selbst auf, müsste
Delphi-Quellcode:
procedure TLivetrack.SetVID(VID : String);
begin
  self.FVID := VID;
end;
heissen

SimStar001 13. Mai 2009 10:51

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Ok , danke.

Irgendwie sieht man manchmal einfach die einfachsten Fehler net! :wall:

DeddyH 13. Mai 2009 10:52

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Glaub nicht, dass das anderen nicht auch schon passiert ist :roll: *pfeif*

mkinzler 13. Mai 2009 10:54

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Zitat:

Glaub nicht, dass das anderen nicht auch schon passiert ist Rolling Eyes *pfeif*
ich glaube schon (fast) jedem.

SimStar001 13. Mai 2009 11:26

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
:-D Das beruhigt mich .... *fg*

Vielen Dank nochmal!

taaktaak 13. Mai 2009 11:28

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Mal 'ne Frage am Rande: Wozu
Delphi-Quellcode:
self.FVID := VID;
hier das self? Sollte doch auch ohne funktionieren

mleyen 13. Mai 2009 11:32

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
VID := VID; säh ja komisch aus.

Ich glaub aber das viele das self. mit aus anderen Sprachen übernehmen und es in Delphi auch überall hinschreiben.

SirThornberry 13. Mai 2009 11:39

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
auch wenn es OT ist:
Das Self hinzuschreiben hat in meinen Augen mehr Vor- als Nachteile. Man sieht dadurch sofort das es sich um eine Variable der Klasse handelt und es keine globale, parameter etc. ist.
Zudem hat man dadurch die Möglichkeit Variablen der Klasse genau so zu benennen wie auch Parameter der Funktion in denen die Variable gesetzt wird.

DeddyH 13. Mai 2009 12:16

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Aus den von Jens genannten Gründen schreibe ich auch immer self davor, obwohl es nicht notwendig ist. Aber man sieht sofort, dass es sich dabei um ein Feld der eigenen Klasse handelt, ohne lange suchen zu müssen. Und wenn dann noch ein with-Block im Spiel ist, kommt man oft um self nicht mehr rum, außer durch Vermeidung von with ;)

SimStar001 13. Mai 2009 12:18

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Ich schreibe das self. auch mit weil es einfach wirklich oft viel übersichtlicher ist.

Klar kann man das auch weglassen, funktioniert auch ohne.
Ich würde aber auch immer empfehlen es mit hinzuschreiben!

taaktaak 13. Mai 2009 12:18

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
@#8
Ok, aber VID:=VID hiesse es ja nicht, sondern FVID:=VID

- aber grundsätzlich verstanden!
Danke :hi:

Blup 13. Mai 2009 12:35

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
In SetFTPDirectory wird FFTPDirectory nicht verändert.
Hier wäre dann vieleicht auch ein GetFTPDirectory angebracht.

OT:
Self macht den ganzen Quelltext nur unübersichtlich.
Meine persönlichen Style-Regeln:
- Parameter heißen bei sämtlichen Set-Methoden "AValue" oder "AIndex".
- Wenn Parameter wie Properties heißen müssen, dann bekommen diese einen einheitlichen Präfix ("A").

Ein "constructur" sollte keine lange Parameterliste haben, daß ist unübersichtlich.
Dann besser die Properties nach dem Erzeugen einzeln zuweisen.
Entsprechende Methoden zum Lesen und Schreiben der Konfiguration zu implementieren ist auch eine gute Idee.

SimStar001 13. Mai 2009 12:40

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Zitat:

Ok, aber VID:=VID hiesse es ja nicht, sondern FVID:=VID
Ganz genau, das war ja auch das Problem vorhin, denn so wurde immer wieder die property von der proberty aufgerufen, weshalb es zum Überlauf kam.

also die Klasse sieht im Moment so aus:

Delphi-Quellcode:
unit Livetrack;

interface

uses IdFTP, IdHTTP, Classes, DateUtils, SysUtils;

type TFTP = class(TIDFTP)
   
    end;

type THTTP = class(TIDHTTP)
    end;

type TLivetrack = class(TObject)
      private
      {private Vars}
      FHTTP : THTTP;
      FFTP : TFTP;
      FCacheDirectory : string;
      FFTPHost : String;
      FFTPDirectory : String;
      FFTPLoginName : String;
      FFTPPassword : String;
      FHTTPUrl : String;
      FFileName : String;
      FVID : String;

      {Set Procedures}
      procedure SetFTPHost(Host : String);
      procedure SetFTPDirectory(Directory : String);
      procedure SetFTPLoginName(LoginName : String);
      procedure SetFTPPassword(Password : String);
      procedure SetVID(VID : String);

      {get Functions}
      function GetFTPHost : String;
      function GetFTPLoginName : String;
      function GetFTPPassword : String;

      public
      {Functions}
      constructor create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String; const VID : string); overload;
      constructor create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String); overload;
      destructor destroy ; override;

      {Normal Functions}
      function download(TimeOut : Integer) : boolean;
      function upload(TimeOut : Integer) : boolean;
      function refresh (const RealName : String; const ATC_Position : String; const Tool : String): boolean;

      {properties}
      property CacheDirectory : String read FCacheDirectory write FCacheDirectory;
      property FTPHost : String read GetFTPHost write SetFTPHost;
      property FTPDirectory : String read FFTPDirectory write SetFTPDirectory;
      property FTPLoginName : String read GetFTPLoginName write SetFTPLoginName;
      property FTPPassword : String read GetFTPPassword write SetFTPPassword;
      property HTTPUrl : String read FHTTPUrl write FHTTPUrl;
      property FileName : String read FFileName write FFileName;
      property VID : String read FVID write SetVID;
      end;

implementation

{Set Procedures}

procedure TLivetrack.SetFTPHost(Host : String);
begin
  self.FFTP.Host := Host;
end;

procedure TLivetrack.SetFTPDirectory(Directory : String);
begin
  if Directory = '' then
    exit;
   
  if self.FFTP.Connected then
    self.FFTP.ChangeDir(Directory);
end;

procedure TLivetrack.SetFTPLoginName(LoginName : String);
begin
  if self.FFTP.Connected then
    exit;

  self.FFTP.Username := LoginName;
end;

procedure TLivetrack.SetFTPPassword(Password : String);
begin
  if self.FFTP.Connected then
    exit;

  self.FFTP.Password := Password;
end;

procedure TLivetrack.SetVID(VID : String);
begin
  self.FVID := VID;
end;
// Ende Set Procedures

////////////////////////////////////////////////////////////////////////////////


{Get Functions}

function TLivetrack.GetFTPHost : String;
begin
  result := self.FFTP.Host;
end;

function TLivetrack.GetFTPLoginName : String;
begin
  result := self.FFTP.Username;
end;

function TLivetrack.GetFTPPassword : String;
begin
  result := self.FFTP.Password;
end;
// Ende Get Functions

////////////////////////////////////////////////////////////////////////////////


{Normal Functions}

function createTimeStamp : string;
begin
  result := inttostr(DateTimeToUnix(now));
end;

// *.csv - Aufbau {VID : TimeStamp : RealName : ATC Position : Tool}
function TLivetrack.refresh(const RealName : String; const ATC_Position : String; const Tool : String) : boolean;

  function datainlist(const TList : TStringlist) : integer;
    var i : Integer;
    begin
      result := -1;

      if TList.Count = 0 then
        exit;

      for i := 0 to TList.Count - 1 do
        if self.FVID = copy(TList.Strings[i],1,pos(':',TList.strings[i]) - 1) then
          begin
          result := i;
          break;

          end;
    end;
   
var TList : Tstringlist;
    Index : integer;
    FileName : string;
    TimeStamp : string;
begin
  result := false;
  TList := TStringlist.Create;
  FileName := self.FCacheDirectory + '\' + self.FFileName;

  try
    if Fileexists(FileName) then
      Tlist.LoadFromFile(FileName);

    Index := datainList(TList);
    TimeStamp := createTimeStamp;
    if Index = -1 then
      TList.add(self.FVID + ':' + TimeStamp + ':' + RealName + ':' + ATC_Position + ':' + Tool)
        else
          TList.strings[Index] := self.FVID + ':' + TimeStamp + ':' + RealName + ':' + ATC_Position + ':' + Tool;
    finally
      result := true;
      end;
     
  TList.SaveToFile(FileName);
  TList.Free;
end;

function TLivetrack.upload(TimeOut : Integer) : boolean;
begin
  result := false;
  self.FFTP.Port := 21;

  self.FFTP.Connect(true,TimeOut);
  if self.FFTPDirectory <> '' then
    self.FFTP.ChangeDir(self.FFTPDirectory);

  try
    self.FFTP.Put(self.FCacheDirectory + '\' + self.FFileName , self.FFileName , false);
    finally
      result := true;
      end;

  self.FFTP.Disconnect;
end;


function TLivetrack.download(TimeOut : Integer) : boolean;
var FileStream : TFileStream;
begin
  result := false;
  FileStream := TFileStream.create(self.FCacheDirectory + '\' + self.FFileName,fmcreate);
  self.FHTTP.Connect(TimeOut);

  try
    self.FHTTP.Get(self.FHTTPUrl + '/' + self.FFileName , FileStream);
    finally
      result := true;
      end;
     
  FileStream.free;
  self.FHTTP.Disconnect;
end;

// Ende Normal Functions

////////////////////////////////////////////////////////////////////////////////

{Constructor}

constructor TLivetrack.create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String);
begin
  inherited create;

  self.FFTP := TFTP.Create(nil);
  self.FHTTP := THTTP.Create(nil);

  // Setzen der Parameter für HTTP und FTP
  self.CacheDirectory := CacheDirectory;
  self.FTPHost := FTPHost;
  self.FTPDirectory := FTPDirectory;
  self.FTPLoginName := FTPLoginName;
  self.FTPPassword := FTPPassword;
  self.HTTPUrl := HTTPUrl;
  self.FileName := FileName;
  self.VID := 'none';

end;

constructor TLivetrack.create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String; const VID : string);
begin
  inherited create;

  self.FFTP := TFTP.Create(nil);
  self.FHTTP := THTTP.Create(nil);

  // Setzen der Parameter für HTTP und FTP
  self.CacheDirectory := CacheDirectory;
  self.FTPHost := FTPHost;
  self.FTPDirectory := FTPDirectory;
  self.FTPLoginName := FTPLoginName;
  self.FTPPassword := FTPPassword;
  self.HTTPUrl := HTTPUrl;
  self.FileName := FileName;
  self.VID := VID;

end;
// Ende Constructor

////////////////////////////////////////////////////////////////////////////////


{Destructor}

destructor TLivetrack.destroy;
begin
  self.FFTP.Free;
  self.FHTTP.free;

  inherited destroy;
end;
// Ende Destructor

////////////////////////////////////////////////////////////////////////////////

end.
Die Idee mit AValue oder AIndex zur Übergabe ist auch ganz gut, denke aber nicht, dass es sinnvoll ist sie immer so zu nennen.
Mit der Namensgebung bei den Übergabeparametern bezwecke ich, dass ich auch in ein paar Monaten noch weiß was ich übergeben soll. Da wäre AValue denke ich net so angebracht...

Was die Übergabe beim Erzeugen betrifft, bin ich einfach zu Faul alles danach aufzurufen, zumal ich beim erzeugen sowieso die ganzen parameter kenne und ich diese in der Regel auch nicht mehr verändere.

quendolineDD 13. Mai 2009 13:15

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Zitat:

Mit der Namensgebung bei den Übergabeparametern bezwecke ich, dass ich auch in ein paar Monaten noch weiß was ich übergeben soll.
Deswegen Dokumentiere ich auch die Funktionen und den Sinn und Zweck der einzelnen Parameter.
Wenn du dir mal zB von JEDI anschaust, wie dort gearbeitet wird, kannst du auch deine Quelltexte langzeitlich und für andere verständlich aufbereiten.

SirThornberry 13. Mai 2009 13:26

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
@quendolineDD: Das wird zwar jetzt OT aber ich kann nicht anders. In unserem Styleguide ist zum Beispiel erwähnt das Quelltext welcher Kommentiert werden muss schlechter Quelltext ist. Und genau der Meinung bin ich auch. Quelltext sollte so geschrieben werden das er ohne Kommentaare verständlich ist.

SimStar001 13. Mai 2009 13:31

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
Danke für den Tip Lars, werd ich mir mal ansehen und ggf. auch verbesserungen vornehmen!

brechi 14. Mai 2009 12:07

Re: Stack Überlauf, beim eruezgen der eigenen Klasse! Wieso?
 
und warum 2x den Constructor

Delphi-Quellcode:
constructor TLivetrack.create(const CacheDirectory : String; const FTPHost : string; const FTPDirectory : string; const FTPLoginName : string; const FTPPassword : string; const HTTPUrl : String; const FileName : String; const VID : string = 'none');
sollte auch gehen.

[edit=mkinzler]Delphi-Tag eingefügt Mfg, mkinzler[/edit]


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:28 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