Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi (Keine) Freude mit Zeigern (https://www.delphipraxis.net/13751-keine-freude-mit-zeigern.html)

Dani 26. Dez 2003 02:59


(Keine) Freude mit Zeigern
 
Frohe Weihnachten allerseits :)

Ich arbeite gerade zum Spass an einem mittelmäßigen Chatprogramm für Delphi, was bisher auch relativ zügig voran ging, aber jetzt scheitert es an einem ziemlich nervigen (weil eigentlich nicht komplizierten) Problem....Zeiger....

Kann mir da evtl. jemand etwas unter die Arme greifen? :gruebel:

In der Haupt-Unit sind nämlich u.A. folgende Typen und Variablen definiert:

Delphi-Quellcode:
type

{TCchatMessage - Träger für alle Art von Datenpacketen, die zwischen Client und Server verschickt werden}
TChatMessage = record
    MsgType   : Byte;
    MsgContent : array[0..1023] of char;
   end;

{TChatRoom - Ein Element innerhalb der Chatroomsm ObjectList}
  TChatroom = class(TObject)
    ClientsInRoom : TList;
    Name : String[30];
   end;

  PChatroom = ^TChatroom;

{TChatRoom - Virtuelle Entsprechung eines Chat-Benutzers und Element der AllClients ObejectList}
  TChatClient = class(TObject)
    Nickname : String[15];
    IPAddr : String[16];
    Room : PChatroom;
    Hash, awaymsg, dndmsg, abouttext : String;
    BannedFromRooms, IgnoredClients : TStrings;
    HasIdentified, IsAdmin: Boolean;
    Status : TClientstatus;
    Thread : PIDPeerThread;
   end;

  PChatClient = ^TChatClient;

var
  Form1: TForm1;
  MsgQueue, AllClients, BanList, Chatrooms: TObjectList;
  //In diesen Listen werden die Chaträume, User usw. gespeichert und verwaltet
Das läuft dann so ab, dass Client und Server sich zuerst Hallo sagen, der Server einen neuen TChatClient in die Allclients Liste einfügt und dem Client dann einen Raum zuweist. Ein paar wichtige Funktionen, die das erledigen sehen so aus:
(die sind glaube ich nicht das Problem, aber glauben hilft ja nix :-/ )

Delphi-Quellcode:
function InitNewClient(IP: String; AThread: PIdPeerThread): TChatClient;
begin
Result := TChatClient.Create;
with Result do
  begin
   Nickname := IP; //temporär, Namenszuweisung erfolgt im nächsten Schritt
   IPAddr := IP;
   Hash := StringToHash(Nickname+IPAddr); (** im Moment noch sinnlos...vielleicht später nützlich [Präadaption :P] **)
   Room := AssignLobby; //Sucht bzw. erzeugt die nächste nicht überfüllte Lobby
   Room.ClientsInRoom.Add(@Result); //ob das funtkioniert?
   awaymsg := '';
   dndmsg := '';
   abouttext := '';

   BannedFromRooms := TStringlist.Create;
   IgnoredClients := TStringlist.Create;

   HasIdentified := false;
   IsAdmin := false;
   
   Status := csAvailable;

   Thread := AThread;
  end;
end;

function CreateRoom(designation: string): TChatroom;
begin
Result := TChatroom.Create;
Result.Name := designation;
Result.ClientsInRoom := TList.Create;
end;

function AssignLobby: PChatRoom;
var i: integer;
begin
//Untersuche Räume - Nächste Lobby die weniger als MaxUsersPerRoom User hat wird zurückgegeben
i := 1;
Result := nil;

 While Result=nil do
  begin
   Result := GetChatroomByName('LOBBY-'+IntToStr(i));
   Inc(i);
   If Result = nil then ChatRooms.Add(CreateRoom('LOBBY-'+IntToStr(i)))
    else
     If Result.ClientsInRoom.Count<MaxUsersPerRoom then
       break;
  end;
end;
Das klappt schon ganz ordentlich, nur eine Funktion zickt noch (kann mir aber nicht sicher sein, dass es die einzige ist) :

Delphi-Quellcode:
function GetChatroomByName(RoomName: String): PChatRoom;
var i: Integer;
begin
Result := nil;
 for i:=0 to ChatRooms.Count-1 do
  If (Chatrooms[i] as TChatroom).Name = RoomName then
   begin
    Result := Pointer( (Chatrooms.Items[i] as TChatRoom));
    break;
   end;
end;
Das Problem: Wenn ich diese Funktion aufrufe, gibt sie zwar einen gültigen Zeiger auf *irgendetwas* anderes als nil zurück, allerdings erhalte ich nur "Datenmüll" bei folgendem Test:
Delphi-Quellcode:
ShowMessage(GetChatroomByName('LOBBY-1').Name);
---------------------------
IP Delphi Chat
---------------------------
m‹À¼ÒJ ( + sehr viele Leerzeichen)
---------------------------
OK
---------------------------


Ich hab schon verschiedene Dinge ausprobiert, da ich dachte es stimme etwas von der Logik her mit der GetChatroomByname Funktion nicht, aber eigentlich müsste sie ja das richtige Ergebnis liefern, oder? :pale:

Viele Grüße an alle DP'ler und danke schonmal fürs lesen! Normalerweise versuche ich nicht unnötig auszuholen beim posten aber das hier ist schon etwas verzwickt :oops:

Luckie 26. Dez 2003 03:13

Re: (Keine) Freude mit Zeigern
 
Hast du auch irgendwo Speicher reserviert für die Daten? Und noch was: Warum sind TChatMessage und TChatRoom Klassen? Sie beinhalten doch keine Methoden, also würde ich da Records nehmen.

Dani 26. Dez 2003 03:23

Re: (Keine) Freude mit Zeigern
 
Am Anfang hatte ich Records benutzt, aber ich konnte leider keine TRecordList finden , daher die Klassen.

Speicher reservieren? Die ganzen Objecte werden von den TObjectLists "geowned" , ich dachte die Sache wäre damit für mich erledigt weil die Methoden der ObjectList die Speicherreservierung und das ganze Management übernehmen...

"Mit TObjectList können Sie eine Liste von Objekten speichern und verwalten. Die Komponente stellt Eigenschaften und Methoden für das Hinzufügen, Löschen, Umsortieren, Suchen, Zugreifen und Sortieren von Objekten zur Verfügung. Ist die Eigenschaft OwnsObjects auf True gesetzt (Voreinstellung), verwaltet TObjectList den Speicher seiner Objekte, das heißt, ein Objekt wird freigegeben, wenn sein Index neu zugewiesen wird, wenn es mit der Methode Delete, Remove oder Clear aus der Liste entfernt wird oder wenn die Instanz TObjectList selbst aufgelöst wird."

Die Objekte werden mit einer Funktion erzeugt und als Ergebnismenge an die Funktion TObjectlist.add() der jeweiligen Liste übergeben.
Delphi-Quellcode:
function CreateObject: TObject;
begin
 Result := TObject.Create;
end;

...

MyObjectList.add(CreateObject);
Muss ich den Pointern auch extra Speicher reservieren mit New() oder genügt das hier?
Delphi-Quellcode:
MyPointer := Pointer(MyObject);
Hab ich das falsch verstanden, dass Pointer nur Zeiger auf Objekte (Adressen) sind und eine feste Größe haben (wie z.B. ein Integer 4 Bytes groß ist)?

Luckie 26. Dez 2003 04:31

Re: (Keine) Freude mit Zeigern
 
Also wenn TObjectList so was wie TList ist, dann muss man vor dem Hinzufügen jeweils für das Element Speiucherreservieren. In der Hilfe steht ja auch nur, dass beim Löschen der Speicher freigegeben wird.

Delphi-Quellcode:
MyPointer := Pointer(MyObject);
Damit castest du ja nur MyObject nach Pointer. Reservier mal mit new speicher.

Ja Pointer sind monmentan 4 Byte groß.

Robert Marquardt 26. Dez 2003 08:49

Re: (Keine) Freude mit Zeigern
 
Delphi-Quellcode:
function GetChatroomByName(RoomName: String): PChatRoom;
var i: Integer;
begin
Result := nil;
for i:=0 to ChatRooms.Count-1 do
  If (Chatrooms[i] as TChatroom).Name = RoomName then
   begin
    Result := Pointer( (Chatrooms.Items[i] as TChatRoom));
    break;
   end;
end;
Warum willst du hier einen Zeiger zurueckliefern?
Ein Objekt ist sowieso schon ein Zeiger.
Du lieferst nicht einen Zeiger auf ein TChatroom sondern den TChatroom-Zeiger selbst.
Delphi-Quellcode:
function GetChatroomByName(RoomName: String): TChatroom;
var i: Integer;
begin
Result := nil;
for i:=0 to ChatRooms.Count-1 do
  If (Chatrooms[i] as TChatroom).Name = RoomName then
   begin
    Result := Chatrooms.Items[i] as TChatroom;
    break;
   end;
end;

Dani 26. Dez 2003 14:14

Re: (Keine) Freude mit Zeigern
 
Zitat:

Ein Objekt ist sowieso schon ein Zeiger.
Das wusste ich nicht, danke euch Beiden!! :thuimb:
Es funktioniert jetzt...


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