• Advertisement

Archived

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

void * deletion / destruction problem

This topic is 5512 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

it seems that whenever i cast some object pointer to a void pointer then delete it the object''s destructor is not called. is this ''normal'' is there anything i can do about it? im trying to build an alloc and forget array class wherein the class allocates an array of void*''s that other objects get inserted into, and when the class is destroyed it will delete each pointer in the array since i dont know what kind of objects will be in the array i cant use anything other than void* i know i ''could'' use templates to have a given array adapt to a type but i dont like using templates and i would like the array to be able to contain many types of objects any help is greatly apreciated=) Raymond Jacobs, Profesional Web Applications Developer, Weekend Game Developer, www.EtherealDarkness.com

Share this post


Link to post
Share on other sites
Advertisement
to have the correct destructor called you have to use a correct pointer

using templates will solve your problem.

I take it that you mean you want to store pointers to unrelated things in your array. How will you know what they all are?

Share this post


Link to post
Share on other sites

yeah i figured templates would work in this case, darn
i hate templates lol

btw, good question i wouldnt know what they ''were''
guess i dont need that feature now=)

ok so templates it is=)

thanks

Raymond Jacobs,
Profesional Web Applications Developer,
Weekend Game Developer,
www.EtherealDarkness.com

Share this post


Link to post
Share on other sites
quote:
Original post by EDI
it seems that whenever i cast some object pointer to a void pointer then delete it the object''s destructor is not called.

That''s because you''re not supposed to do that.
quote:

is this ''normal'' is there anything i can do about it?

Yes. Don''t call delete with a void*.
quote:

wherein the class allocates an array of void*''s

Oh heck...
quote:

i know i ''could'' use templates to have a given array adapt to a type but i dont like using templates and i would like the array to be able to contain many types of objects

Then you need some means of type-discrimination, where each type that goes into the array is entered into a structure along with a tag representing the type code. Then, every time you perform an operation on the type (like deleting), you need to first cast it to the type indicated by the tag. Nice to see yet another person emulating dynamic typing in C++.

Share this post


Link to post
Share on other sites
actually, thinking about it, what you''re saying is all wrong!

when you say ''other objects get inserted into'', what exactly do you mean by that? that the object is created by the array or the object already exists?

Share this post


Link to post
Share on other sites
ok just to clear that up here is the thing,

i make a new array class

FC_Array myarray;


i insert a new object into it

myarray.InsertObject(new Sprite());


now if i want to have the array do the garbage collection for me,

then i set

myarray.WillFree(true);


internaly the array dynamicly allocs an array of void *''s

void **m_list;

problem with that is because when the array tries to free the elements it they are currently being stored as void*

which when delted doesnt call the destructor... which is my problem

now im probably going to have to implement templates which i hate to do cause i feel they complicate things and are just plain ugly=)

also

"
Then you need some means of type-discrimination, where each type that goes into the array is entered into a structure along with a tag representing the type code. Then, every time you perform an operation on the type (like deleting), you need to first cast it to the type indicated by the tag. Nice to see yet another person emulating dynamic typing in C++.
"

even using a structre wont work since the single structure cant anticipate all the possible object types ill be using






Raymond Jacobs,
Profesional Web Applications Developer,
Weekend Game Developer,
www.EtherealDarkness.com

Share this post


Link to post
Share on other sites
Really?


typedef struct {
void *data;
char dataType;
} Object;


enum dataTypes {
DATA_CHAR_ARRAY = 0
...
...
};


// during deallocation,
switch (objectInstance->dataType) {
case DATA_CHAR_ARRAY:
delete (char *)objectInstance->data;
break;
...
}


Welcome to dynamic typing!

[edited by - johnnie2 on January 23, 2003 10:17:36 AM]

Share this post


Link to post
Share on other sites
Thats all well and good but what if i make an object called

UnkownToAllButMe

the array isnt going to know how to cast to that type of object because for all accounts said object doesnt exist.


since the deletion routines must be done internaly in the class

within the destructor of the array class

i would need somthing like

case OBJECT_TYPE_UNKNOWNTOALLBUTME:
delete (UnknownToAllButMe*)lpdata;
break;


but since at the time when this array class was made the UnkownToAllButMe object hadnt even been thought of, thus i never coded a case for it





Raymond Jacobs,
Profesional Web Applications Developer,
Weekend Game Developer,
www.EtherealDarkness.com

[edited by - EDI on January 23, 2003 10:31:43 AM]

Share this post


Link to post
Share on other sites
you could make the InsertObject member function templated
It creates a wrapper round the class pointer and puts the wrapper into the array.
The wrapper is derived from some base class and also takes the type information from the template. It will know how to delete the pointer it is wrapping correctly.

or you could try boost''s any class

Share this post


Link to post
Share on other sites
quote:
Original post by EDI
even using a structre wont work since the single structure cant anticipate all the possible object types ill be using

Partially correct. You could emulate more fully a dynamic type system. Perhaps, in your pursuit for dynamic typing, you would drop the pretence of static typing and build a fuller dynamic system. Forget the type-safe new and delete operators, and use malloc and free instead. free takes a void*. However, in doing this you also need to drop the pretence of using C++ classes for creating types, and instead you create a generic structure that holds both the type identifier, and a sub-structure representing the physical make-up of the object.

No longer do you control lifetime of instances by saying:

int i = new int(10);
// ...
delete i;


But instead do something like:

arglist args;
args.push_back("10");
var i = ("i", make_instance("int", args));
// ...
delete_instance(symbol_from_string("i"));

Or maybe you could even implement a simple garbage-collection scheme to save explicitly deleting instances.

Welcome to Greenspun's tenth rule!

[edited by - SabreMan on January 23, 2003 10:38:53 AM]

Share this post


Link to post
Share on other sites
what i would really like is to be able to define the array

FC_Array ar;


and the first object that i insert defines what kind of objects the class can hold

doing somthing like FC_Array myclassarray;
{
just seems so ...ick... especialy if i want to pass a pointer of this array to another function that is going to fill it with another type, i would have to instead make the function return a new array which i would then have to delete.

or have the function return a copy of the array which will be slow due to the need for cloning the array
}

is that possible? im not very experienced in using templates

could somone give me an example?

Raymond Jacobs,
Profesional Web Applications Developer,
Weekend Game Developer,
www.EtherealDarkness.com

[edited by - EDI on January 23, 2003 10:46:39 AM]

Share this post


Link to post
Share on other sites
One way to store anything in a list is to derive the list item holders from a base class, and make the derived class a template.


  
class Base
{
public:
Base() {}
virtual ~Base() {}

virtual char* GetStoredType()=0;
};

template<class T> class Item : public Base
{
public:
Item( T* item, char* type );
virtual ~Item() { delete m_item; }

virtual char* GetStoredType() { return m_type; }
T* GetItem() { return m_item; }

private:
T* m_item;
char* m_type;

};

List<Base*> list;

Foo foo1;
Bar bar1;
Item<Foo> *item1 = new Item<Foo>( foo1, "foo" );
Item<Bar> *item2 = new Item<Bar>( bar1, "bar" );

list.Add( dynamic_cast<Base*>(item1) );
list.Add( dynamic_cast<Base*>(item2) );


This is more of a suggestion than a solid solution, you may well still need to use void*''s in places. Not terribly pretty, but it will work (probably with a bit of tweaking).

Share this post


Link to post
Share on other sites
i see,

so there is no way of getting away from the templates eh?



Raymond Jacobs,
Profesional Web Applications Developer,
Weekend Game Developer,
www.EtherealDarkness.com

Share this post


Link to post
Share on other sites
quote:
Original post by EDI
so there is no way of getting away from the templates eh?

I''ve told you a way of doing it without templates.

Share this post


Link to post
Share on other sites

  
#ifndef ANY_ARRAY_H
#define ANY_ARRAY_H

#include <deque>
#include <algorithm>

struct wrapperBase {
virtual ~wrapperBase(){}
};

template<class T>
class wrapper : public wrapperBase {
T* thing_;
public:
wrapper(T* thing) : thing_(thing){}
~wrapper(){delete thing_;}
};

inline void deleteWrapper(wrapperBase* ptr) {
delete ptr;
}

class anyArray {
std::deque<wrapperBase*> things_;
public:
anyArray(){};
~anyArray(){std::for_each(things_.begin(), things_.end(), deleteWrapper);};
template<class T>
add(T* thing) {
things_.push_back(new wrapper<T>(thing));
}
};

#endif



  
#include "any_array.h"
class fruit {};
class texan {};

int main() {
anyArray things;
things.add(new int(5));
things.add(new double(4.5));

things.add(new fruit);
things.add(new texan);

return 0;
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Actually, you don''t need templates or object type flags. paulc is nearly there in his post. First, you need a base class from which all objects that can be inserted into your array are derived from - paulc''s base class will do the job. The important bit here is to declare the destructor as virtual.
Then, instead of having an array of void *''s, have an array of Base *''s:
Base **the_array;
Then, calling delete on any item in the array will call the derived object''s destructor. So, for example:
class AClass : public Base
{
virtual ~AClass () {};
// some stuff
}

Base **my_array = new Base* [num_elements];
my_array [0] = new AClass;

// stuff

delete my_array [0]; // here, AClass''s destructor is called

Of course, the down side here is that you can''t cast from a Base* to an AClass* unless you''ve got RTTI enabled (not the best) or have a mechanism to get the derived object''s pointer (something like: virtual void *Base::GetDerivedPointer (void); and reinterpret cast the result - not pretty, I know).
If you''ve got common functionality across all derived objects, then put declarations for these in the base class (as pure virtual functions) and you won''t need the preceding type nastiness.

Skizz

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
Actually, you don't need templates or object type flags. paulc is nearly there in his post. First, you need a base class from which all objects that can be inserted into your array are derived from - paulc's base class will do the job. The important bit here is to declare the destructor as virtual.
Then, instead of having an array of void *'s, have an array of Base *'s:

OK smartass, let's see you add an int to the array.

Oh yeah, and this solution requires *every* object to inherit from a common ancestor, which is equivalent to a loss of type-safety (object* is semantically equivalent to void*). What you have now is a situation where you need to downcast from "object" all over the place. Since you don't know what object you actually have, you have to manually write (or otherwise generate) a chain of dynamic_casts to query for each and every type (sound similar to anything mentioned earlier?), ensuring that you order the sequence of dynamic casts most-derived to least-derived, else you may slice the object. You have to write this code everywhere that you do something with an object*. To factor out the commonality so that you only write it one place, you need a common point at which you despatch calls on the object*. That would involve some fairly complicated logic for identifying the object, getting a hold of it, querying for a function, despatching the function, getting a hold of the return value (which presumably would be of type object*), and handing the return value back to the caller in object* format. Hence the sequence begins again to advance to the next program state. Hang on a minute...

Dynamic language anybody?

[edited by - SabreMan on January 23, 2003 12:53:29 PM]

Share this post


Link to post
Share on other sites
i''ll test some of these methods and get back to you,

thanks all=)

Raymond Jacobs,
Profesional Web Applications Developer,
Weekend Game Developer,
www.EtherealDarkness.com

Share this post


Link to post
Share on other sites
I finaly got it,

the code PeteWood posted was super helpful,

i basicly now have a class *wrapper* that contains a pointer to
template

so when you create a wrapper class you give it a type

Wrapper *lpw=new Wrapper;


and to take this one step further

the InsertObject function takes a parameter of template

which is then passed off to the wrapper

so in the array class i store an array of Wrapper pointers which hold the pointer to the object

template InsertObject(T *lp)
{
Wrapper *lpw=new Wrapper;
lpw->m_lpdata=lp;
//store the wrapper ptr into the array
}

then latter on, on array destructor

i go thru the array of wrappers

and if the WillFree flag is true

then i call delete on lpw->m_lpdata;
then i delete the wrapper itself


it requires no external change to my current api

destructors get called and eveyone is happy=)

thank you all VERY much for your help=)






Raymond Jacobs,
Profesional Web Applications Developer,
Weekend Game Developer,
www.EtherealDarkness.com

Share this post


Link to post
Share on other sites
glad to help.

how are you getting the pointer out of the array? edit: or is it just a bucket that will eventually be emptied but you don't need to get specific items?

could you show us your code (we'll pull it to pieces, I promise )

[edited by - petewood on January 23, 2003 2:05:50 PM]

Share this post


Link to post
Share on other sites
basicly whenever i need to retive it i can cast to void*

simply because it will be cast to the ''right'' object in the end

i dont have it fully implemnted in my FC_Array,FC_LinkList or FC_Dictionary classes yet, but i did a quick mock up mirroring your posted code and it worked=)



Raymond Jacobs,
Profesional Web Applications Developer,
Weekend Game Developer,
www.EtherealDarkness.com

Share this post


Link to post
Share on other sites
quote:
Original post by SabreMan
Welcome to Greenspun''s tenth rule!


What''s that??

quote:
Original post by SabreMan
Dynamic language anybody?


Not quite there yet... but getting closer.




Share this post


Link to post
Share on other sites
quote:
Original post by petewood
<Greenspun''s Tenth Rule of Programming: "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp.">use your initiative


My initiative is to click your initiative and the "quote".

Thanks.

Share this post


Link to post
Share on other sites

  • Advertisement