Archived

This topic is now archived and is closed to further replies.

JtM

explicit call to destructors in template classes...

Recommended Posts

I''ve never made a post here before so please bare with me :D I''ve started using a memory manager (the one from fluid studios) in a project. I kept getting memory leaks, and it seemed that delete[] wasen''t calling the destructor of the elements in an array. The problem was that the structs I were using had thier own destructors that got rid of some dynamic arrays within them but were not being called. A few questions: 1)When you delete[] an array (created with new) should it call the destructors for each element? 2)If not then is it ok to call the destructors of each element then delete the array normally? Here''s the code of the class I was having problems with (I''ve since fixed the memory leaks but I''m still not sure if this is the way to go about it).
  



template <class T> class vector_list
{        
        int size; //size of the array...

        T* list;  //template pointer thingy.

    public:

        //default constructor.

        vector_list() {
           list = NULL;
           size = 0;
        }       
       
        //default list bigger than zero?

        vector_list(int size2) {
           list = NULL;
           size = size2;
           if(size>0) list = new T[size];           
        }       

        //create a blank object.

        T& new_object() {                        
            T* temp;
            temp = new T[size+1];
            
            for(int i=0;i<size;i++) {
                temp[i] = list[i];            
            }
            delete[] list;
            list = new T[size+1];
            for(int i=0;i<size;i++) {
                list[i] = temp[i];            
            }            
            delete[] temp;
            size++;
        }

        /* create a new object from a pointer 
           (so we can initialise classes)
           note that the original object is copied
           and then destroyed. */
          
        void new_object(T* object) {                        
            T* temp;
            temp = new T[size+1]; //create a temporary array

            
            //copy stuff to array.

            for(int i=0;i<size;i++) {
                temp[i] = list[i];            
            }
            delete[] list;
            list = new T[size+1]; //effectively resize list array.            

            //copy stuff back.

            for(int i=0;i<size;i++) {
                list[i] = temp[i];            
            }                        
            delete[] temp;
            list[size] = *object;
            delete[] object;
            size++;                               
        }
        
        //delete an object and shift the rest.                         

        void delete_object(int object) {
        
            if(object<0||object>size) return;
                
            T* temp;
            int n=0;
            temp = new T[size];            
            for(int i=0;i<size;i++) {
                temp[i] = list[i];            
            }
            delete[] list;
            list = new T[size-1];
            for(int i=0;i<size;i++) {
                if(i != object) {
                    list[n] = temp[i];
                    n++;            
                }
            }
            delete[] temp;                                
        }        

        ~vector_list() {                        
              if(size > 0) {                                    
                  for(int i=0;i<size;i++) {
                      //explicitly call destructor since-

                      //delete[] doesn''t seem to do it.

                      (&list[i])->T::~T();                  
                  }   
              }
              delete[] list;
        }

        
        T& operator[](int i) {
            return(list[i]);        
        }

        int get_max() {return(size);}
        void show_max() {cout <<size<<endl;}        
};
  
I know it probably looks fairly messy and uncommented (not to mention backwards and unwieldy) but this is what i''ve ended up with. Next time I think I''ll start using STL instead.

Share this post


Link to post
Share on other sites
Are you delete''ing void pointers? Destructors don''t get called in that case. Remeber to make your destructor virtual if you destroy a derived class through a base class pointer.

Answering your other questions, yes, delete[] does call destructors for each array element in turn.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Share this post


Link to post
Share on other sites
If your asking "Do you need to call delete for each array in an array of array''s or an STL data?" collection then yes you do

Cheers
Chris

Share this post


Link to post
Share on other sites
Thanks for the replies... here are the related structs i''ve been working with. image_set_t holds generic information that sprites use and also animation information. The bitmaps need to be destroyed once the image set is deleted so I added the descructor inside the struct (don''t know if this effects delete[] in any way), which also takes care of the animation data. I noticed that I got memory leaks from these two things that should be destroyed in the destructor.


  

typedef struct frame_t {
int delay;
int img;
};
typedef struct anim_t {
frame_t* frame;
int frames;
};
typedef struct image_set_t {
int offx,offy;
int x1,y1,x2,y2,ax,ay;
int xspr, yspr;
int images;
char target[32];
BITMAP** handle;
bool bUseAnim;
anim_t* anim;
int anims;

image_set_t() {
handle=NULL;
images=0;
}
~image_set_t() {

if(bUseAnim==1) {
for(int i=0;i<anims;i++) {
delete[] anim[i].frame;
}
delete[] anim;
}

if(handle) {
for(int i=0;i<images;i++) {
destroy_bitmap(handle[i]);
}
delete[] handle;
}
}

};



I tried changing img_set_t into a class and it made no difference but once I put in the code to call the destructors it worked fine. But does that mean the destructors could be called twice?

Thanks in advance :D

Share this post


Link to post
Share on other sites
Put a printf or cout trace in the destructors and check. Also trace something where you allocate the objects and check that the constructors match the destructors. If you are using MSVC, in debug mode you get a trace of unfreed blocks in the debug window when the program terminates. If you double click on the unfreed report, it often takes you to the source line which allocated the memory.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Share this post


Link to post
Share on other sites