Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem mit TObject.Classname (https://www.delphipraxis.net/129526-problem-mit-tobject-classname.html)

implementation 20. Feb 2009 15:01


Problem mit TObject.Classname
 
In meiner Funktion habe ich einen Zeiger auf ein TObject.
Ich möchte dort den Klassennamen als String auslesen.
Delphi-Quellcode:
function NotifyToList(item: PObject): Word;
var i: Word;
begin
  while ItemUsed[i] do Inc(i);
  ItemUsed[i]:=true;
  ServerList[i] := item;
  Result := i;
  OutputLine('WSID '+IntToHex(i,4)+' is stored for a '+item^.ClassName);
end;
Doch beim Aufruf hält das Programm mittendrin an.
Es bricht nicht ab. Es stoppt einfach nur.
Es passiert nichts weiter.
Wenn ich
Delphi-Quellcode:
item^.Classname
entferne, läuft das Programm weiter, aber natürlich wird nur "WSID 0001 is stored for a " ausgegeben.

Wo liegt das Problem bei TObject.Classname?
Was gibt es für Alternativen?

----------[EDIT]------------

Was ist das für'n S*#%§ß?
Nachdem ich den Teil wieder weggenommen hatte, habe ich ihn nun noch einmal wieder eingefügt.
Und? Was dann?
Es hat funktioniert!!!
Und warum musste ich das jetzt erst posten, damit das funzt?
Das müllt doch nur die DP voll...

Problem seltsam gelöst.

mkinzler 20. Feb 2009 15:05

Re: Problem mit TObject.Classname
 
Klassenvariablen sind schon Zeiger (Referenzen)

implementation 20. Feb 2009 15:10

Re: Problem mit TObject.Classname
 
@mkinzler: dann mach ich eben einen Zeiger auf den Klassenzeiger. ;-)
war wohl nicht das problem... [siehe oben]

mkinzler 20. Feb 2009 15:21

Re: Problem mit TObject.Classname
 
Und was soll der Sinn sein?

Hawkeye219 20. Feb 2009 15:32

Re: Problem mit TObject.Classname
 
Hallo,

vielleicht hilft es auch schon, wenn du die lokale Variable i geeignet initialisierst. Dann schreibst du nicht unkontrolliert im Speicher herum.
Was passiert eigentlich in deiner Routine, wenn alle Elemente im Feld ItemUsed besetzt sind?

Gruß Hawkeye

mjustin 20. Feb 2009 15:35

Re: Problem mit TObject.Classname
 
Zitat:

Zitat von implementation

Wo liegt das Problem bei TObject.Classname?
Was gibt es für Alternativen?

----------[EDIT]------------

Problem seltsam gelöst.

Ja, funktioniert tadellos. Ich würde TObject statt PObject bevorzugen. Vielleicht ist das aber auch eine interne Codeverschleierungsmethode, vorgeschrieben von einem C(++)-Programmierer :)

Cheers,

implementation 20. Feb 2009 16:35

Re: Problem mit TObject.Classname
 
Zitat:

Zitat von Hawkeye219
Was passiert eigentlich in deiner Routine, wenn alle Elemente im Feld ItemUsed besetzt sind?

Das wird nicht passieren.
ItemUsed und Serverlist sind Arrays von 0 bis 1023, und so viele Elemente wird das Programm niemals benötigen.

phreax 20. Feb 2009 16:57

Re: Problem mit TObject.Classname
 
Zitat:

Zitat von implementation
Das wird nicht passieren.
ItemUsed und Serverlist sind Arrays von 0 bis 1023, und so viele Elemente wird das Programm niemals benötigen.

Da Du deine lokale Variable nicht initialisierst, kann diese im Zweifelsfall einen beliebigen Wert annehmen, und du bekommst einen falschen Index....

Besser so:
Delphi-Quellcode:
function NotifyToList(item: PObject): Word;
var i: Word;
begin
  i := 0;
  while ItemUsed[i] do Inc(i);
  ItemUsed[i]:=true;
  ServerList[i] := item;
  Result := i;
  OutputLine('WSID '+IntToHex(i,4)+' is stored for a '+item^.ClassName);
end;
Grüße phreax

Hawkeye219 20. Feb 2009 17:35

Re: Problem mit TObject.Classname
 
@implementation

Wenn du auf die PObject-Zeiger nicht verzichtest, kannst du sehr leicht in die nächste Falle geraten. Solltest du die Adresse einer lokalen Objektreferenz an deine Routine NotifyList übergeben, könnte das Array ServerList bald ungültige Referenzen enthalten. Dies passiert immer dann, wenn die aufrufende Routine beendet wird und ihre lokalen Variablen somit zerstört werden:

Delphi-Quellcode:
procedure TestProc;
var
  Server : TServer;
begin
  :
  NotifyToList(@Server);
  :
  // Nach dem Beenden der Routine TestProc existiert die Variable "Server" nicht mehr.
  // Die in "ServerList" eingetragene Adresse verweist also auf undefinierte Daten.
end;
Gruß Hawkeye

himitsu 20. Feb 2009 18:03

Re: Problem mit TObject.Classname
 
nja, wenn er sich den Speicher für den Zeiger noch mit anlegt, dann würde es auch damit gehn. :roll:
Delphi-Quellcode:
procedure TestProc;
var
  Server : TServer;
  P: PObject;
begin
  :
  New(P);
  P^ := Server:
  NotifyToList(P);
  :
end;
Aber wie bereits gesagt, ist TObject (nnd Nachkommen) schon ein Zeiger(Refferenz) auf die Objectdaten.
Also würde ein Cast ausreichend sein.
Delphi-Quellcode:
procedure TestProc;
var
  Server : TServer;
begin
  :
  NotifyToList(Pointer(Server));
  :
end;

Hawkeye219 20. Feb 2009 19:05

Re: Problem mit TObject.Classname
 
@himitsu

Es könnte jetzt jemand auf die Idee kommen, den Aufruf aus dem zweiten Code-Block mit der Original-Routine zu kombinieren. Das wird nicht gut gehen...

Gruß Hawkeye

himitsu 20. Feb 2009 20:17

Re: Problem mit TObject.Classname
 
Delphi-Quellcode:
var ServerList: Array[..] of TObject;

function NotifyToList(item: TObject): Word;

// oder besser gleich TServer statt TObject

var ServerList: Array[..] of TServer;

function NotifyToList(item: TServer): Word;
PS: warum eigentlich ItemUsed?
Delphi-Quellcode:
i := 0;
while not Assigned(ServerList[i]) do Inc(i);
ServerList[i] := item;

// aka (Vorherigs halten viele abver für schöner/verständlicher)

i := 0;
while ServerList[i] = nil do Inc(i);
ServerList[i] := item;
und die Übergabe dann nur noch so:
Delphi-Quellcode:
NotifyToList(Server);

implementation 5. Mär 2009 16:46

Re: Problem mit TObject.Classname
 
Wenn ich keine Adressen benutze, sondern direkt die Klassenreferenz (TObject), dann wird jedes mal eine AccessViolation ausgelöst.
Also geht es so nicht.

himitsu 5. Mär 2009 16:51

Re: Problem mit TObject.Classname
 
Eigentlich geht es :angel:


wie versuchst du es denn derzeit? (etwas Code wäre eventuell nicht schlecht)

implementation 6. Mär 2009 12:14

Re: Problem mit TObject.Classname
 
Der Aufruf:
Delphi-Quellcode:
procedure TWdServer.WSIDCreate;
begin
  FWSID := NotifyToList(self);
  // mit FWSID := NotifyToList(TObject(self)); hab ichs auch schon versucht
end;
und
Delphi-Quellcode:
type
  TServerList = array[0..1023] of TObject;
var
  ServerList: TServerList;

[...]

function NotifyToList(item: TObject): Word;
var i: Word;
begin
  ...
  ServerList[i] := item;
  ...
end;
Bei "ServerList[i] := item;" wird die AccessViolation ausgelöst.

himitsu 6. Mär 2009 13:51

Re: Problem mit TObject.Classname
 
Zitat:

Zitat von implementation
Delphi-Quellcode:
function NotifyToList(item: PObject): Word;
var i: Word;
begin
  while ItemUsed[i] do Inc(i);
  ItemUsed[i]:=true;
  ServerList[i] := item;
  Result := i;
  OutputLine('WSID '+IntToHex(i,4)+' is stored for a '+item^.ClassName);
end;

meckert Delphi bei dir eigentlich noch wegen dem undefinierten i?

Delphi-Quellcode:
var ServerList: Array[0..1023] of TObject;

function NotifyToList(Item: TObject): Word;
begin
  Result := Low(ServerList);
  while Assigned(ServerList[Result]) do
    if Result < High(ServerList) then Inc(Result)
    else raise Exception.Create('Liste ist voll');
  ServerList[Result] := Item;
  OutputLine(Format('WSID %.4x is stored for a %s', [Result, Item.ClassName]));
end;


// so das Freigeben von Items:
FreeAndNil(ServerList[i]);

implementation 6. Mär 2009 15:54

Re: Problem mit TObject.Classname
 
dann kommt nicht einmal eine Fehlermeldung.
Das Programm bricht einfach ab.


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