Probleme anscheinend mit malloc, calloc und realloc



  • Hallo,
    ich bin neu hier und werf mal ein großes Hallo in die Runde.

    Nun zu meinem Problem.
    Es handelt sich um eine eigentlich einfache Klasse, die eine Liste von generischen Zeigern darstellt. Bis zu zwei Elementen in der Liste funktioniert es wunderbar. Sobald diese Liste mehr als zwei Elemente hat ändern sich die Zeiger. Meistens wird das zweite Element zum NULL-Zeiger. Dies geschieht irgendwie in der Prozedur TPtrList::Add(void * ) während das dritte Element hinzugefügt wird. Genauer: Sobald ich über TPtrList::Items[int] auf die drei Elemente zugreifen können müsste kommt der Fehler (ohne dass ich wirklich darauf zugreife, nur mithilfe von überwachten Ausdrücken). Hier die Dateien (TPtrList::Delete() hab ich auskommentiert weil noch nicht gebraucht. Auch TPtrList::Clear() hab ich nur vorsorglich geschrieben, sie wird auch nie aufgerufen):

    ptrlist.h

    #ifndef ptrlistH
    #define ptrlistH
    #include <alloc.h>
    
    class TPtrList{//Wie TStringList oder TByteList, nur mit generischen Zeigern
            private:
                    void **StrtPtr;
                    int pCount;
                    void * GetItem(int Index){return (void *) *(StrtPtr+Index*sizeof(void *)); }
                    void SetItem(int Index,void *Value){ *(StrtPtr+Index*sizeof(void *))=Value; }
            public:
                    void Add(void *ToAdd);
                    void Delete(int Index,int Length);
                    __property int Count={read=pCount};
                    __property void *Items[int]={read=GetItem,write=SetItem};
                    void Clear(void)
                    {//Löscht den Inhalt der Liste
                            free(StrtPtr);
                            pCount=0;
                            StrtPtr=NULL;
                    }
                    TPtrList()
                    :StrtPtr(NULL),
                     pCount(0)
                    {;}
    };
    #endif
    

    ptrlist.cpp

    #include <vcl.h>
    #pragma hdrstop
    #include "ptrlist.h"
    #pragma package(smart_init)
    
    void TPtrList::Add(void *ToAdd)
    {//Fügt einen Eintrag hinzu
            void **NewStrtPtr=(void **) calloc(pCount+1,sizeof(void *));
            for(int i=0;i<pCount;i++)//Alte Werte übertragen
                    *(NewStrtPtr+i*sizeof(void *))=GetItem(i);
            *(NewStrtPtr+(pCount)*sizeof(void *))=ToAdd;
            free(StrtPtr);
            pCount++;
            StrtPtr=NewStrtPtr;
    }
    
    void TPtrList::Delete(int Index,int Count)
    {//Löscht Count Einträge ab Index
            ;/*pCount=pCount-Count;
            for(int i=0;i<Count;i++)
                    SetItem(Index+i,GetItem(Index+i+Count));
            StrtPtr=(void **) realloc(StrtPtr,sizeof(void *)*pCount);*/
    }
    

    Ich hab auch schon folgende Versionen von TPtrList::Add(void 😉 probiert.

    void TPtrList::Add(void *ToAdd)
    {//Fügt einen Eintrag hinzu
            void **NewStrtPtr=(void **) malloc(pCount+1,sizeof(void *));
            for(int i=0;i<pCount;i++)
                    *(NewStrtPtr+i*sizeof(void *))=GetItem(i);
            *(NewStrtPtr+(pCount)*sizeof(void *))=ToAdd;
            free(StrtPtr);
            pCount++;
            StrtPtr=NewStrtPtr;
    }
    
    void TPtrList::Add(void *ToAdd)
    {//Fügt einen Eintrag hinzu
            pCount++;
            StrtPtr=(void **) realloc(StrtPtr,sizeof(void *)*pCount);
            SetItem(pCount-1,ToAdd);
    }
    

    Ich hab auch schon probiert die Klasse nur für eine feste Anzahl von Elementen (10) einzurichten

    ptrlist.h

    #ifndef ptrlistH
    #define ptrlistH
    #include <alloc.h>
    
    class TPtrList{//Wie TStringList oder TByteList, nur mit generischen Zeigern
            private:
                    void **StrtPtr;
                    int pCount;
                    void * GetItem(int Index){return (void *) *(StrtPtr+Index*sizeof(void *)); }
                    void SetItem(int Index,void *Value){ *(StrtPtr+Index*sizeof(void *))=Value; }
            public:
                    void Add(void *ToAdd);
                    void Delete(int Index,int Length);
                    __property int Count={read=pCount};
                    __property void *Items[int]={read=GetItem,write=SetItem};
                    void Clear(void)
                    {//Löscht den Inhalt der Liste
                            free(StrtPtr);
                            pCount=0;
                            StrtPtr=0;
                    }
                    TPtrList()
                    :StrtPtr(NULL),
                     pCount(10)
                    {StrtPtr=(void **) malloc(10*sizeof(void *));}
    };
    #endif
    

    ...und dann Add() so umzuschreiben:

    void TPtrList::Add(void *ToAdd)
    {//Fügt einen Eintrag hinzu
            *(StrtPtr+(pCount)*sizeof(void *))=ToAdd;
            pCount++;
    }
    

    ..der Fehler aber blieb der gleiche...und wär ja auch keine Lösung gewesen.

    Findest ihr irgendwas? Ich verwende parallel eine ähnliche Klasse, nur für __int8 und nicht für generische Zeiger. Sie funktioniert genauso (ist sogar noch weitaus umfangreicher), mit ihr hatte ich aber von Anfang an keine Probleme.
    Danke schonmal für eure Hilfe... 🙂

    Felix

    P.S.: Ich weiß dass ich noch einen Destruktor brauche, der Fehler entsteht aber schon früher und darum dürfte es nicht daran liegen.

    P.P.S.: Ich benutz den Borland C++ Builder 6, aber auch mit der 4er Version habe ich es ausprobiert.



  • Hallo

    Wenn du schon einen C++ Compiler hast, solltest du auch C++ Mittel benutzen. Entweder verwendest du die bereits fertige Klasse std::list, oder du erstellst dir selber eine, aber verwendest statt der typlosen Zeiger auch Templates.

    bis bald
    akari



  • Es gibt auch noch die VCL-Variante TList.
    [edit]
    PS:
    Wenn du die Klasse schon unbedingt selber schreiben willst, warum malloc/calloc/free und nicht new/delete? Die ganzen Multiplikationen mit void* beim Zugriff sollten auch nicht nötig sein. Bei GetItem und SetItem solltest du testen ob der Index nicht überschritten wird, sonst erzeugst du undefiniertes Verhalten.[edit]


Anmelden zum Antworten