AddObject und -1



  • Hallo,

    hier mal ein paar Zeilen Code:

    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    { int W;
      W=-2; ListBox1->Items->AddObject("Minus 2",(TObject *)W);
      W=-1; ListBox1->Items->AddObject("Minus 1",(TObject *)W);
      W=0;  ListBox1->Items->AddObject("Null",   (TObject *)W);
      W=1;  ListBox1->Items->AddObject("Eins",   (TObject *)W);
      W=2;  ListBox1->Items->AddObject("Zwei",   (TObject *)W);
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::ListBox1DblClick(TObject *Sender)
    { int x=(int)ListBox1->Items->Objects[ListBox1->ItemIndex];
      Edit1->Text=IntToStr(x);
    }
    

    Wenn man nun also in der ListBox doppelt klickt, wird der an den TString angehängte Integer W in einen String konvertiert und im Edit1 angezeigt.

    Funktioniert auch ganz prima, außer bei der -1. Da semmelt er mit mit einem EStringListError (Der Index der Liste überscheitet das Maximun (1) ) ab.

    Hab ich ein Brett vorm Kopf? 😕

    Gruß

    Daniel



  • Ich weiß ja nicht, ob der Cast von int auf TObject* und wieder zurück so toll ist.

    DMarko schrieb:

    ListBox1->Items->AddObject("Minus 2",(TObject *)W);
      // ...
      int x=(int)ListBox1->Items->Objects[ListBox1->ItemIndex];
    

    Schreib Dir doch ein kleine Wrapper-Klasse, sowas in der Form:

    // Header
    class TIntegerObject: public TObject
    {
    public:
      virtual __fastcall TIntegerObject(int Value);
    
      __property int Value = {read=FValue, write=FValue}
    private:
      int FValue;
    };
    
    //cpp
    __fastcall TIntegerObject::TIntegerObject(int Value): TObject()
    {
      FValue = Value;
    }
    

    Die kannst Du dann so benutzen:

    ListBox1->Items->AddObject("Minus 2",new TIntegerObject(W));
      // ...
      int x=((TIntegerObject*)ListBox1->Items->Objects[ListBox1->ItemIndex])->Value;
    

    Oder verwende irgendwas besser geeignetes wie eine map.

    Gruß,

    Alexander



  • DMarko schrieb:

    Funktioniert auch ganz prima, außer bei der -1.

    Wow!
    Ich habe das mal reproduziert und es sollte imho nicht passieren.
    -1 ist zwar nicht wirklich ein sinnvoller Zeiger-Wert. Aber daß da ein "List index out of bounds" ausgeworfen wird ist einigermaßen mysteriös.
    Vielleicht kann ja mal jemand einen Blick in die Quellen werfen ...?



  • dschensky schrieb:

    -1 ist zwar nicht wirklich ein sinnvoller Zeiger-Wert. Aber daß da ein "List index out of bounds" ausgeworfen wird ist einigermaßen mysteriös.

    Ja nicht...
    Ich weiß ja das die Nummer mit (TObject *)int nicht ganz sauber ist, aber bis dato hat sie blendent funtioniert. Und -1 ist genau so wenig sinnvoll wie -2. Aber das geht.... *wunder

    Nur noch mal zur Info: Ich benutze den BCB 5.0 pro



  • Hallo

    Tausche mal den -1 Eintrag mit dem -2 Eintrag. Du wirst sehen das geht auch nicht. Wenn positive Zahlen eingetragen werden funktioniert alles. Nimm also lieber diese Wrapper-Klasse. Damit solltest du dann keine Probleme haben.
    @dschensky
    Ich hab mal einen Blich in die Quellen geworfen, aber auf Anhieb auch nichts erkannt. Ich vermute mal das hier infolge des Casts irgendein Speichbereich überschrieben wird. Die Exception kommt immer bei Position 1, egal welche negative Zahl drinsteht.

    Ciao



  • Braunstein schrieb:

    Tausche mal den -1 Eintrag mit dem -2 Eintrag. Du wirst sehen das geht auch nicht.

    Nein. Bei mir pfeift er immer bei W=-1 ab.

    Braunstein schrieb:

    Wenn positive Zahlen eingetragen werden funktioniert alles. Nimm also lieber diese Wrapper-Klasse. Damit solltest du dann keine Probleme haben.

    Werd ich auch in ner stillen Stunde mal machen. Für die tägliche Arbeit brauch ich die -1 nicht wirklich. Die Frage hat ja generell auch nur akademischen Charakter.

    Braunstein schrieb:

    Die Exception kommt immer bei Position 1, egal welche negative Zahl drinsteht.

    Er wirft mir die Position wo W=-1 ist. Wenn ich die an Position 4 setze, dann kommt auch in der Expetion genau dieser Wert.

    Gruß Daniel



  • DMarko schrieb:

    Bei mir pfeift er immer bei W=-1 ab.

    Kann ich bestätigen. Und es ist nicht der Cast (warum auch!?), sondern der Zugriff auf das "Objects"-Array.
    Ich habe mal einen Blick in die Pascal-Quellen gworfen ($(BCB)\Source\Vcl\classes.pas). Soweit ich den Pascal-Code verstehe, wird beim Zugriff auf den Indexer "Objects" (TStringList.GetObject) an keiner Stelle der Wert des Zeigers überprüft. Also ich sehe eigentlich keine Ursache für die Exception.

    So nebenbei bin ich auf die maximal mögliche Anzahl von Einträgen für String-Listen gestoßen (wollte ich immer schon mal wissen):

    MaxListSize = Maxint div 16;
    

    (gilt wohl auch für TList)



  • dschensky schrieb:

    Soweit ich den Pascal-Code verstehe, wird beim Zugriff auf den Indexer "Objects" (TStringList.GetObject)...

    ... was aber alles völlig irrelevant ist, da die Property "Items" von TListBox (entgegen der CB-Hilfe) vom Typ "TListBoxStrings" ist. TListBoxStrings wiederum hat die Methode "GetObject", welche einen Bug enthält.



  • Hallo dschensky,

    erst mal ein Lob für Deine Ausdauer.

    Aber ist es denn ein Bug?

    Zumindest in der Anwendung hier mit dem gecaste von int nach TObject* hätte ich mit Problemen gerechnet.
    Meiner Meinung nach kann der Wert FFFF als Zeiger auf ein TObject nicht vorkommen und somit finde ich den Wert als Fehlerwert i.O. und würde das nicht unbedingt als Bug sehen.

    Grüße Joe_M.



  • Hi,

    Joe_M. schrieb:

    Zumindest in der Anwendung hier mit dem gecaste von int nach TObject* hätte ich mit Problemen gerechnet.

    also beide Typen (int und TObject*) sind 4-Byte Bitmuster und casten sollte erlaubt sein und keine Probleme bringen.

    int i = -1;
    TObject* o = (TObject*)i;
    i = (int)o;
    

    Ob das "schön" ist, steht auf einem anderen Blatt.

    Joe_M. schrieb:

    Meiner Meinung nach kann der Wert FFFF als Zeiger auf ein TObject nicht vorkommen und somit finde ich den Wert als Fehlerwert i.O. und würde das nicht unbedingt als Bug sehen.

    Wenn Borland dies als Fehler betrachtet, dann wurde die Fehlerbehandlung zumindest sehr inkonsequent umgesetzt. Es geht ja um diese Zeile:

    if Longint(Result) = LB_ERR then Error(SListIndexError, Index);
    

    Diese Zeile findet sich nur in TListBoxStrings.GetObject. Warum nicht schon bei der Zuweisung des Wertes und warum nicht auch in TStringList?
    Imho hat die Zeile in TListBoxString.GetObject nichts zu suchen. Es sollte nicht Aufgabe dieser Klasse sein, den Rückgabewert auf Gültigkeit zu prüfen.
    TListBoxStrings.Objects ist eine Property, die das Setzen beliebiger Werte zuläßt, beim Abrufen jedoch bei bestimmten Werten Ausnahmen auswirft - von diesem Standpunkt aus ist das für mich ein Bug.



  • dschensky schrieb:

    ...sind 4-Byte Bitmuster...

    Ja und genau deswegen bin ich der Meinung, dass der Zeigerwert FFFF nicht vorkommen kann.

    dschensky schrieb:

    Es sollte nicht Aufgabe dieser Klasse sein, den Rückgabewert auf Gültigkeit zu prüfen ... von diesem Standpunkt aus ist das für mich ein Bug.

    So gesehen hast Du dann recht. Da das Posting in dem von Dir angegebenen Link von 2001 ist und der Bug immer noch da ist, sieht Borland das entweder anders, oder ist zu faul das zu korrigieren.


Log in to reply