Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi BUG? - Boolean Variable wird willkürlich auf true gesetzt (https://www.delphipraxis.net/133228-bug-boolean-variable-wird-willkuerlich-auf-true-gesetzt.html)

HeinzJ 28. Apr 2009 08:43


BUG? - Boolean Variable wird willkürlich auf true gesetzt
 
Ausgangslage ist eine Klasse mit einem Boolean Wert XYZ.
Im Create wird diese noch einmal explizit auf FALSE gesetzt.

Beim Debuggen wird der Breakpoint, wo XYZ auf true gesetzt wird, NICHT erreicht.
Trotzdem hat die Variable an anderen Stellen im Code nervigerweise den Wert TRUE ?!!

Kennt jemand dieses Verhalten und kann mehr darüber sagen?

Thx, HeinzJ

Mithrandir 28. Apr 2009 08:45

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
*räusper* Glaskugel ist im Urlaub.... *räusper*

Will sagen, ein wenig Code wäre nicht schlecht, da zumindest die Variablen meiner Klassen sich so verhalten, wie ich es gerne hätte... ;)

hoika 28. Apr 2009 09:00

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Hallo,

mach aus der Variablen ein property,
und setze einen Breakpoint auf die Set-Methode.

Mögliche Ursachen wären:
1. der vorm Monitor ;)
2. Speicherüberschreibung

Für 1., naja ;)

Für 2.
Memcheck oder fastmm4 benutzen.

Ausserdem die Variable auf Änderungen überwachen.

2. geht nur zur Laufzeit.
Setze einen Breakpoint auf deinen Konstruktor.
Wird er angesprungen, Popup-Menü "Bei Änderung anhalten" für die Variable setzen.

Das muss übrigens bei jedem Programm-Start neugemacht werden,
weil die Adresse der Variable überwacht wird und die sich bei jedem Start ändert.


Ich würde aber erst mal mit dem property anfangen.


Heiko

HeinzJ 28. Apr 2009 09:03

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Glaskugel stimmt schon.
Hier der Abgespeckte Code zur veranschaulichung der oben beschriebenen Problematik.

Delphi-Quellcode:
unit Abgespeckt;

interface

uses
   Windows, Messages, SysUtils, Variants, Classes,
   Graphics, Controls, Forms, DB, ADODB, Dialogs;

AClass = class(TObject)
   protected
      FRelationList: TStringList;
      HasReadRelationListFromDB: Boolean;
      function GetiNumMembers: smallint;
   public
      constructor Create(X: array of const);
      property RelationList: TStringList read GetRelationList;
      property NumberOfMembers: smallint read GetiNumMembers;
   end;

implementation

constructor AClass.Create(X: array of const);
// *************************************************
var
   key: string;
begin
   inherited Create;
   HasReadRelationListFromDB := false;
   FRelationList := nil;
end;

function AClass.GetiNumMembers: smallint;
// ............................................
begin
   MessageDlg(inttostr(RelationList.Count), mtInformation, [mbOK], 0);
end;

function AClass.GetRelationList: TStringList;
begin
   if not HasReadRelationListFromDB then //<< Hier wird HasReadRelationListFromDB als true im Debugger angezeigt.
   begin
      HasReadRelationListFromDB := true; // << Diese Zeile wird nie erreicht
      FRelationList := TStringList.Create;
      // read someting from a db.
   end;
   Result := FRelationList;
end;


end.

sirius 28. Apr 2009 09:10

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Hast du in den Constructor mal einen Breakpoint gesetzt um zu schauen, ob das Programm dort überhaupt vorbeikommt?

Und: Wie erstellst du die Klasse?

hoika 28. Apr 2009 09:11

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Hallo,

du verschweigst uns aber den X Parameter.
Ausserdem fehlt die Benutzung der Klasse.

Wie ist denn der Wert genau am end des Konstruktors ?


Heiko

HeinzJ 28. Apr 2009 09:29

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Der Constructor wird erreicht
X ist eine Array of const, momemtan nur ein Integer [1]
Die Klasse wird per Obj:= AClass.Create([oid]); kreiert.
Am Ende des Create hat HasReadRelationListFromDB den Wert FALSE.

hoika 28. Apr 2009 09:34

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Hallo,

und jetzt müssten wir halt noch wissen,
wo du Obj.RelationList benutzt.
Und vor allem, was du sonst noch so im Code treibst ;)

Probier doch mal das mit dem property/Breakpoint aus.


Edit:
Zitat:

wo du Obj.RelationList benutzt.
Habe die Verwendung gefunden ... ;)


Heiko

sirius 28. Apr 2009 09:56

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Edit 2:
Doch, jetzt habe ich mich von mir selber austricksen lassen.
funktioniert bei mir hervorragend:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

AClass = class(TObject)
   protected
      FRelationList: TStringList;
      HasReadRelationListFromDB: Boolean;
      function GetiNumMembers: smallint;
      function GetRelationList: TStringlist;
   public
      constructor Create(X: array of const);
      property RelationList: TStringList read GetRelationList;
      property NumberOfMembers: smallint read GetiNumMembers;
   end;



var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var c:AClass;
begin
  c:=AClass.Create([1]);
  c.NumberOfMembers;
end;

constructor AClass.Create(X: array of const);
// *************************************************
var
   key: string;
begin
   inherited Create;
   HasReadRelationListFromDB := false;
   FRelationList := nil;
end;

function AClass.GetiNumMembers: smallint;
// ............................................
begin
   MessageDlg(inttostr(RelationList.Count), mtInformation, [mbOK], 0);
end;

function AClass.GetRelationList: TStringList;
begin
   if not HasReadRelationListFromDB then //<< Hier wird HasReadRelationListFromDB als true im Debugger angezeigt.
   begin
      HasReadRelationListFromDB := true; // << Diese Zeile wird nie erreicht
      FRelationList := TStringList.Create;
      // read someting from a db.
   end;
   Result := FRelationList;
end;

smudo 28. Apr 2009 09:58

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Hallo,

ich kann leider nicht erkennen, wo die Funktion GetiNumMembers zum Tragen kommt.
Da wird MessageDlg aufgerufen und ich habe momentan auch das Problem, dass bei einigen Aufrufen der Dialog einfach übergangen wird.
Könnte es evtl. das gleiche Problem sein?

Gruß
René

thkerkmann 28. Apr 2009 10:15

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Hi,

mit diesem Code kann nix passieren....

Ich behaupte mal folgendes:

Die Variablendeklartion
Delphi-Quellcode:
     
      FRelationList: TStringList;
      HasReadRelationListFromDB: Boolean;
ist nicht original - ich vermute mal VOR HasReadRelationListFromDB wird noch ein statisches array sein, in dessen Speicher du irgendwo mit einem Index größer als die eigentliche Größe hineinschreibst.
Da das ganze nicht den Variablenbereich deines Objektes sprengt, wird kein Fehler angezeigt - es sei denn du schaltest mal RangeChecking ein.

Habe selber nach so einem Fehler schon Tage gesucht. Das macht richtig Spass. :wall:

Assertor 28. Apr 2009 10:45

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Hi,

Zitat:

Zitat von HeinzJ
Delphi-Quellcode:
unit Abgespeckt;

interface

...

implementation

...

function AClass.GetRelationList: TStringList;
begin
   if not HasReadRelationListFromDB then
   begin
      ShowMessage('xyz'); // hier Breakpoint setzen!
      HasReadRelationListFromDB := true;
      ...
   end;
   ...
end;

end.

Ich würde mal die Projektoptionen prüfen und alle Optimierungen abschalten bzw. die Debug Optionen einschalten. Setz den Breakpoint wie oben gezeigt und pack ein ShowMessage o.ä. rein.

Es ist stark davon auszugehen, daß ein "if not x then x := true" ziemlich schnell (weg)optimiert wird. Ganz sicher kannst Du gehen, in dem Du Dir die besagte Codestelle im Debugger während der Ausführung als asm anzeigen lässt.

Gruß Assertor

Muetze1 28. Apr 2009 10:52

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Zitat:

Zitat von HeinzJ
Der Constructor wird erreicht
X ist eine Array of const, momemtan nur ein Integer [1]
Die Klasse wird per Obj:= AClass.Create([oid]); kreiert.
Am Ende des Create hat HasReadRelationListFromDB den Wert FALSE.

Das AClass sieht mir ganz danach aus, als wenn hier eine Class Of XXX verwendet wird. Dabei ist zu beachten, dass dann der Constructor von XXX als virtuell deklariert werden muss und alle nachfolgenden Ableitungen diesen überschreiben müssen, wenn sie einen Constructor haben, da diese sonst nicht aufgerufen wird.

Und warum eine boolsche Variable, wo doch assigned(FRelationList) genau dieses boolsche Ergebnis liefert ohne zusätzliche Variable?

Phoenix 28. Apr 2009 10:56

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Ich würde mir die Adresse des boolschen Wertes raussuchen und einen Datenhaltepunkt setzen. Dort siehst Du dann, wann der Wert an dieser Speicheradresse geändert wird. Das ist aller Wahrscheinlichkeit nach der effizienteste Weg den Fehler einzukreisen.

himitsu 28. Apr 2009 11:00

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Zitat:

Zitat von Muetze1
Das AClass sieht mir ganz danach aus, als wenn hier eine Class Of XXX verwendet wird. ...

sieht nur so aus ... siehe Post #4 ... er hat seine Klasse einfach nur AClass getauft :stupid:

@HeinzJ: sicher daß du nicht irgendwo 'nen Pufferüberlauf oder irgendwas Dergleichen hast?
(welcher praktisch an "falschen" Stellen im RAM rumschreibt)

stoxx 28. Apr 2009 12:26

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Hallo HeinzJ,

der Fehler bei solchen "völlig" unerklärbaren Fehlern, sitzt meistens VOR dem Computer :-)

Jetz änder Deine Klasse mal, und prüfe ob vielleicht eine Nachfolgende Klasse oder irgendjemand anderes die Variable ändert :-)
Denn ich vermute, genau deswegen hast Du die Variablen im protected Teil..



Delphi-Quellcode:
AClass = class(TObject)
strict private // oder nur private

  FHasReadRelationListFromDB : boolean;
  function GetiNumMembers: smallint;

protected
      FRelationList: TStringList;
public
      constructor Create(X: array of const);
      property HasReadRelationListFromDB: Boolean read FHasReadRelationListFromDB;
      property RelationList: TStringList read GetRelationList;
      property NumberOfMembers: smallint read GetiNumMembers;
end;


implementation

function AClass.GetRelationList: TStringList;
begin
   if not FHasReadRelationListFromDB then // jetzt wird es gehen :-)
   begin
      FHasReadRelationListFromDB := true; // << Diese Zeile wird nie erreicht  (jetzt schon)
      FRelationList := TStringList.Create;
      // read someting from a db.
   end;
   Result := FRelationList;
end;



im übrigen, wenn Du die Variable nur als "Information" brauchst, ob die List schon da ist, kannst Du auch mit

Delphi-Quellcode:
if not assigned(FRelationList) then begin
    FRelationList := TStringList.Create;
end;
Result := FRelationList;
die Variable sparen

HeinzJ 29. Apr 2009 07:39

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Danke für alle Antworten
Abhilfe hat bei mir nur die Löschung aller DCUs sowie das Laden des Projektes über die DPR geschafft.
Keine Ahnung wieso.

HeinzJ

Bbommel 29. Apr 2009 10:28

Re: BUG? - Boolean Variable wird willkürlich auf true gesetz
 
Zitat:

Zitat von hoika
2. geht nur zur Laufzeit.
Setze einen Breakpoint auf deinen Konstruktor.
Wird er angesprungen, Popup-Menü "Bei Änderung anhalten" für die Variable setzen.
Das muss übrigens bei jedem Programm-Start neugemacht werden,
weil die Adresse der Variable überwacht wird und die sich bei jedem Start ändert.

Das eigentliche Problem scheint ja gelöst zu sein, aber zu diesem Daten-Haltepunkt habe ich mal eine Nachfrage: Kann es sein, dass es diese Funktion im Popup-Menü bei D2009 nicht mehr gibt? Wenn ich bei einem Programm von mir das oben beschriebene durchführen will, dann finde ich in einem Popup-Menü zwar eine unglaubliche Menge an Einträgen, aber nicht diesen.

Ich kann dann manuell in den Haltepunkten einen Daten-Haltepunkt setzen und statt einer Adresse dann den Variablennamen eingeben, dann klappt es. Geht natürlich, aber ist schon ein bisschen umständlicher (zumal mir bisher nie klar war, dass man das nur zur Laufzeit kann, hätte ja sein können, dass Delphi die Adresse bei jedem Start selbst neu ermittelt, falls möglich...), und daher die Frage, ob ich zu blöd bin, den Eintrag im Popup-Menü zu finden oder ob man wirklich diesen kleinen Umweg gehen muss?

Bis denn
Bommel


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