delete a void pointer

Started by
8 comments, last by guitarman 21 years, 10 months ago
I am writing a linked list class CLinkedList. it''s nodes are base off of the CListNode class which has a void pointer to the data, like so:
  
class CListNode
{
  public:
    ...
  private:
    void* _data;
};

class CLinkedList
{
  public:
    ...
  private:
    CListNode* _list;
};
  
When I add nodes to the list, it works just fine. But when I try to delete the list, it won''t delete. I know this because my constructors and destructors in CListNode print to the console when called. Here is the destructor code for the CListNode class:
  
CListNode::~CListNode()
{
  if (_data)
  {
    delete _data;
    _data = NULL;
  }
}
  
Any help would be appreciated.
[source]#define Jesus 1[/source]
Advertisement
Firstly, you are much better off using std::list than rolling your own.

Secondly, make sure your CLinkedList destructor destroys all the nodes :

  CLinkedList::~CLinkedList{  while( _list )  {     CListNode* next = _list->next;     delete _list;     _list = next;  }}  


Thirdly, if you use CListNode as a base class, make sure its destructor is virtual (otherwise the destructor called is determined by the static type of the pointer, not the dynamic type of the object).

Fourthly, deleteing void pointers never calls a destructor. To (roughly) quote SabreMan quoting the Standard "If you call delete on anything but a pointer to a base of your object, the results are undefined". Thus your data will not get cleaned up properly. (void* is for people who know what they''re doing).

Finally, have a nice day.



Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Deleting void pointers is isn't legal as far as I know. You should look into templates.

Quick example:


  template <class CListType> class CListNode{  public:    ...  private:    CListType* _data;};template <class CListType> class CLinkedList{  public:    ...  private:    CListNode<CListType> * _list;}; /* somewhere else */CLinkedList<int> list_of_integers;  


[edited by - smart_idiot on June 5, 2002 12:55:11 PM]
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.
I encountered a problem with templates. When I wanted to save a temporary copy of the list (to loop thru it), I got a debug assertion message. I overloaded the ''='' operator, and it still didn''t work. I guess templates are the way I need to go...
[source]#define Jesus 1[/source]
quote:Original post by smart_idiot
Deleting void pointers is isn''t legal as far as I know.

Sure it is. If it points to an object with a dtor, the object''s dtors won''t be called, but the memory will be freed.
quote:
You should look into templates.

Agreed. Specifically, std::list.
I''m going to have to disagree a little... while std::list is a terrific thing, I strongly believe that everyone needs to make their own working version of a linked list at least once in their coding careers.

Otherwise, yes, use templates. Using void* as a data type is generally unnecessary unless you''re doing something unusual.

-fel

~ The opinions stated by this individual are the opinions of this individual and not the opinions of her company, any organization she might be part of, her parrot, or anyone else. ~
I want to dig in and make a list class myself, w/o using stl (using templates). How would I overcome the assignment problem mentioned above? i.e.

  CLinkedList<CType> type;type.AddItem(new CType());CLinkedList<CType> copy = type; // debug assertion error  
[source]#define Jesus 1[/source]
Overload the assignment operator or use pointer''s to list''s
"THE INFORMATION CONTAINED IN THIS REPORT IS CLASSIFIED; DO NOT GO TO FOX NEWS TO READ OR OBTAIN A COPY." , the pentagon
i tried those too.
[source]#define Jesus 1[/source]

Look up the 'explicit' keyword in C++, and you'll probably discover that:


  CLinkedList<CType> type;CLinkedList<CType> copy = type;   


is equivalent to:


  CLinkedList<CType> type;CLinkedList<CType> copy(type);  


Notice that you're not actually assigning anything: you're initializing a new object. The type of constructor used to instantiate the second object is called a copy-constructor. By default, the compiler generates a copy-constructor that copies all members of the original object (like the default assignment operator).

In the above example, the constructor used to instantiate 'type' allocates memory, but the constructor used for 'copy' doesn't; it merely copies all members (pointers) of 'type'. So you end up with two objects that have members pointing at a single set of data. Also, problems arise when you try to free the memory in the destructor, because you're deallocating the same memory twice.

btw:

  CLinkedList<CType> type;CLinkedList<CType> copy;copy = type;  


This does call the assignment operator.

Here's an example to play around with:


  template<typename T>    class type    {  public:    type()         { p_ = new T; }    type(const type& t)         { p_ = new T(*t.p_); }    ~type()         { delete p_; }      type& operator=(const type& t)         {         *p_ = *t.p_;         return *this;         }  private:    T* p_;    };int main()    {    type<int> t1;      // construct    type<int> t2 = t1; // copy construct    type<int> t3(t1);  // copy construct    type<int> t4;      // construct    t4 = t1;           // assign    }  



When you're allocating resources in a constructor you almost always need a copy-constructor and an assignment operator too. If necessary, make them both private to prevent copying.

[edited by - kvh on June 6, 2002 10:31:05 AM]

This topic is closed to new replies.

Advertisement