In my application I am creating and returning an array filled with dynamically allocated objects from a derived class like this:
void someGetter(std:vector<DerivedClass> & returnV)
{
BaseClass* base = object->clone(); // "object" is a "unique_ptr<BaseClass>"
DerivedClass* derived = dynamic_cast<DerivedClass*> (base);
if (derived != nullptr)
{
returnV.push_back(*derived);
}
else
{
delete base;
}
}
This obviously creates a memory leak (valgrinds helps me here) because derived is never deleted.
I have tried to free the allocated memory like this:
delete &returnV[0];
It doesn't give any compilation errors/warnings and the code still runs fine. but valgrind reports a few additional errors (invalid read, invalid free) on that line of code and the leak is still there.
Is there any way to free the memory returned like this? Or should i return unique_ptr's instead of the objects ?
If you are going to create a vector that holds values of type Derived then the code is correct except for the memory leak. Note that the object you need to free is not the one in the container (which is a copy) but rather the one that you cloned:
void someGetter(std:vector<DerivedClass>& returnV)
{
BaseClass* base = object->clone(); (object is a unique_ptr<BaseClass>)
DerivedClass* derived = dynamic_cast<DerivedClass> (base);
if (derived != nullptr)
{
returnV.push_back(*derived);
}
delete base;
}
Additionally if clone() does what it says (i.e. it clones the object) then you can avoid the operation by first testing with dynamic_cast whether the base object is a DerivedClass. If it is then insert into the container the copy and avoid the cloning.
Simple answer - always delete base.
if (derived != nullptr)
{
returnV.push_back(*derived);
}
delete base;
Vector takes a copy of derived - so clone object is not needed anymore.
[UPDATE]
I hope you have virtual destructor in BaseClass - if not - then add it.
And one more warning: it might happen that base->clone() returns something more derived than derived:
class MoreDerivedClass : public DerivedClass {};
Then this code succeed even if real class of base is MoreDerivedClass:
DerivedClass* derived = dynamic_cast<DerivedClass> (base);
You can use typeid() to check real type of base...
[UPDATE2]
Consider to change a little your design - and keep clones of your base in vector of unique_ptr of DerivedClass:
void someGetter(std:vector<std::unique_ptr<DerivedClass>> & returnV)
{
if (dynamic_cast<DerivedClass*>(base.get()) != nullptr)
{
returnV.push_back(dynamic_cast<DerivedClass*>(base->clone()));
}
}
First off, the design seems very questionable to me: You have at once a polymorphic hierarchy, and also a container that holds values of a specific member of that hierarchy. There's no end to the problems you're inviting. It would seem far more sensible to have a std::vector<std::unique_ptr<Base>>.
Anyway, here's a moderately safe and efficient way to insert into the container only those objects whose dynamic type matches precisely. It assumes that every class in the hierarchy has an accessible copy constructor.
void someGetter(std:vector<DerivedClass> & returnV)
{
if (typeid(*object) != typeid(DerivedClass)) { return; }
returnV.insert(static_cast<DerivedClass&>(*object));
}
The semantics of this are slightly different from yours, because your code would allow the case where *object is of a strictly more derived type than DerivedClass, and the copying into the vector would slice the object. The present code does not suffer from this problem.
Update (after your comment): If DerivedClass is indeed final (and please mark it as such!), then the following does without typeid:
void someGetter(std:vector<DerivedClass> & returnV)
{
if (DerivedClass * p = dynamic_cast<DerivedClass *>(object.get()))
{
assert(typeid(*p) == typeid(DerivedClass)); // beware of slicing!
returnV.insert(*p);
}
}
Yes, push_back uses the copy constructor. I think David is saying that your code should be
void someGetter(std:vector<DerivedClass>& returnV)
{
DerivedClass*derived = dynamic_cast<DerivedClass*>(object.get());
if (derived != nullptr)
returnV.push_back(*derived);
}
avoiding the cloning and deleting altogether.
Note added in edit: We must not pass the pointer obtained from unique_ptr<>.get() on to any function which may potentially keep a copy, defying the whole point of unique_ptr. The above code doesn't do that.
Related
I am attempting to implement the command and strategy design patterns in C++.
I have an interface for a command, and an interface for a strategy (a different strategy is assigned to each player, so a player may be manual, AI aggressive, AI defensive, AI random... etc). The strategies have a series of functions which return a unique pointer of type ICommand (eg the command interface) which point to an instance of a derived command class. The idea is to create some command in my strategy in a particular way, and then return the unique pointer to the particular command to the game (the invoker of commands) which execute the commands, regardless of what that command is.
My following questions are these:
if I move an instance of a derived class which is pointed to by a unique pointer of a base class, will I get object slicing?
if so, what would be a better way of handling moving around objects regardless of their type ?
Here is my code. Note that I only included the code for the command choose_combo, as the rest would be somewhat redundant:
I have an interface for my standard command:
class Igame_command {
protected: // protected, since Igame_command is an interface.
player &p;
game_model &gm;
Igame_command(player p, game_model gm) : p(p), gm(gm) {}
public:
virtual void execute() = 0;
};
I then have some derived class which implements the above interface:
class choose_combo_c : private Igame_command {
combo c;
int vp;
public:
void set_combo(combo c) { this->c = c; }
void set_vp(int vp) { this->vp = vp; }
combo get_combo() { return c; }
int get_vp() { return vp; }
choose_combo_c::choose_combo_c(player &p, game_model &gm);
void execute() override;
};
I then have an interface for my strategy:
class Istrategy {
protected:
application &app;
game_model &gm;
player &p;
Istrategy(application &app, game_model &gm, player &p) : app(app), gm(gm), p(p) {}
public:
virtual std::unique_ptr<Igame_command> choose_combo(
std::vector<combo> &available_combos, std::vector<int> &available_combos_vp) = 0;
};
For example, for the manual strategy, choosing combo:
std::unique_ptr<Igame_command> manual_strategy::choose_combo(
std::vector<combo> &available_combos, std::vector<int> &available_combos_vp) override {
// code to have the player make a choice, it sets the int choice...
choose_combo_c* ccc = new choose_combo_c(p, gm);
ccc->set_combo(available_combos.at(choice));
ccc->set_vp(available_combos_vp.at(choice));
return std::unique_ptr<Igame_command> (new choose_combo_c(std::move(*ccc)));
}
unique_ptr<T> stores a T*, not a T, so you won't get any object slicing in your example.
But you do have a memory leak, the ccc object you allocate is not being deleted by anyone, you're move constructing a new object from it, but leaking the original itself. The code within manual_strategy::choose_combo should be written as
auto ccc = std::make_unique<choose_combo_c>(p, gm); // create a unique_ptr<choose_combo_c>
// do stuff with it
ccc->set_combo(available_combos.at(choice));
ccc->set_vp(available_combos_vp.at(choice));
// simply return it here, a unique_ptr<Igame_command>
// will be constructed from the unique_ptr<choose_combo_c>
return ccc;
You can't "move" raw pointers - not meaningfully, anyway. You can meaningfully move a unique_ptr, but that doesn't move the object anywhere, it only means that the ownership of that pointed-to object (as allocated memory) moves to someplace/someone else.
That's not what you're doing, though; your code moves your temporary object into a newly-allocated object (which causes a memory leak, as #Preatorian points out).
What would be a better way of handling moving around objects regardless of their type ?
Working with pointers is actually a reasonable way for doing object "moves" irrespective of their types: You simply never (or rarely) actually move any objects, you only work with pointers to them. You might not be able to use typed unique_ptrs if you want type-obliviousness, but you could use void * or unique_ptr<void> pointers with custom deleters.
Another alternative is to use std::any's, without pointers. If the objects are small, moving these is cheap, and if they're big, they're hiding pointers inside, so moving them is again cheap. This alternative in safer in the sense that instead of segmentation violation and reinterpreting garbage, you'll just get exceptions if you try the wrong type.
I have a tricky situation. Its simplified form is something like this
class Instruction
{
public:
virtual void execute() { }
};
class Add: public Instruction
{
private:
int a;
int b;
int c;
public:
Add(int x, int y, int z) {a=x;b=y;c=z;}
void execute() { a = b + c; }
};
And then in one class I do something like...
void some_method()
{
vector<Instruction> v;
Instruction* i = new Add(1,2,3)
v.push_back(*i);
}
And in yet another class...
void some_other_method()
{
Instruction ins = v.back();
ins.execute();
}
And they share this Instruction vector somehow. My concern is the part where I do "execute" function. Will it work? Will it retain its Add type?
No, it won't.
vector<Instruction> ins;
stores values, not references. This means that no matter how you but that Instruction object in there, it'll be copied at some point in the future.
Furthermore, since you're allocating with new, the above code leaks that object. If you want to do this properly, you'll have to do
vector<Instruction*> ins
Or, better yet:
vector< std::reference_wrapper<Instruction> > ins
I like this this blog post to explain reference_wrapper
This behavior is called object slicing.
So you will need some kind of pointer. A std::shared_ptr works well:
typedef shared_ptr<Instruction> PInstruction;
vector<PInstruction> v;
v.emplace_back(make_shared<Add>());
PInstruction i = v[0];
Keep in mind that PInstruction is reference-counted, so that the copy constructor of PInstruction will create a new "reference" to the same object.
If you want to make a copy of the referenced object you will have to implement a clone method:
struct Instruction
{
virtual PInstruction clone() = 0;
...
}
struct Add
{
PInstruction clone() { return make_shared<Add>(*this); }
...
}
PInstruction x = ...;
PInstruction y = x->clone();
If performance is an issue than you can look at std::unique_ptr, this is a little trickier to manage as move semantics are always required, but it avoids the cost of some atomic operations.
You can also use raw pointers and manage the memory manually with some sort of memory pool architecture.
The underlying problem is that to have a polymorphic type the compiler doesn't know how big the subclasses are going to be, so you can't just have a vector of the base type, as it won't have the extra space needed by subclasses. For this reason you will need to use pass-by-reference semantics as described above. This stores a pointer to the object in the vector and then stores the object on the heap in blocks of different sizes depending on what the subclass needs.
No, that will not work; you are "slicing" the Add object, and only inserting its Instruction part into the array. I would recommend that you make the base class abstract (e.g. by making execute pure virtual), so that slicing gives a compile error rather than unexpected behaviour.
To get polymorphic behaviour, the vector needs to contain pointers to the base class.
You will then need to be careful how you manage the objects themselves, since they are no longer contained in the vector. Smart pointers may be useful for this; and since you're likely to be dynamically allocating these objects, you should also give the base class a virtual destructor to make sure you can delete them correctly.
You may want to do a couple things, A: change the type of "v" to "vector", B: managed your memory with the "delete" operator. To answer your question, with this approach, yes, but you will only be able to access the interface from "Instruction", if you KNOW the type of something an "Instruction" pointer is pointing to I would suggest using dynamic_cast if you need to access the interface from, say, "Add".
I'm trying to figure out the memory leaks that I'm having.
I have these (simplified) classes (can not be changed, I have to work with these):
class Base
{
bool baseBool;
Base(Base&){};
virtual ~Base();
}
class Derived1 : public: Base
{
char* text;
Derived1(Derived1&);
~Derived1();
}
class Derived2 : public: Base
{
int num;
Derived2(Derived2&);
~Derived()
}
Derived1 Copy constructor
Derived1::Derived1(Derived1& derived):text("")
{
text=new char[strlen(text)+1]; //assign enough memory + 1
strcpy(text,derived.text); //copy existing aText into new objects aText
}
Then I have a struct used to manipulate them
struct Container
{
Container& operator=(Container&);
Base** bases
}
In the overloaded operator= for struct Container I'm making a deep copy of the Container objects. Like so:
Container& Container::operator=(Container& R)
{
int i,j,k;
for(i=0;i<MAX;i++)
delete bases[i];
delete[]bases;
bases=new Base*[MAX];
for(j=0;j<MAX;j++)
answers[j]=0;
for(k=0;k<MAX;k++)
{
if(dynamic_cast<Derived1 *>(R.bases[k]))
bases[k]=new Derived1(*(dynamic_cast<Derived1 *>(R.bases[k])));
else
bases[k]=new Derived2(*(dynamic_cast<Derived2 *>(R.bases[k])));
}
return *this;
}
This part of the code works if I were to assign a newly created Container object using the overloaded = operator
Like so in my main
Container containers[2];
bases = new Base*[2];
bases[0] = new Derived1("boooo");
bases[1] = new Derived2(3);
containers[0]=*(new Container(bases)); //uses the overloaded operator= OK
But if I were to assign two already made Container objects to each other like so:
containers[0]=containers[1];
Following debugging it crashes on
for(i=0;i<MAX;i++)
delete bases[i];
Saying
HEAP[ass3.exe]: Heap block at 00729268 modified at 00729295 past requested size of 25
ass3.exe has triggered a breakpoint.
HEAP[ass3.exe]: Invalid address specified to RtlValidateHeap( 00720000, 00729270 )
ass3.exe has triggered a breakpoint.
Which is why I think I have memory leaks because Derived1 has a char*.
Glad for any input.
Thanks! I hope I was clear enough...
Edit: I do have an empty base copy constructor, and the derived cc does exist as well. Maybe I went to simple for the example.
It looks like MAX is a number greater than the size of bases ie. bases may only have 5 entrys while MAX could be 10. In this case, once you get past the end of bases (bases[5] does not exist if the size is only 5 because the numbering starts at 0). I typically use a vector instead of an array and my code for the for loop would look like this:
for(i=0;i<bases.size();i++)
delete bases[i];
This ensures that your for loop does not go past the end of bases.
From the example, you've given you need to make sure that the 'bases' member of struct Container itself is actually allocated, and initialized.
From the symptoms you've expressed (crashing on the first iteration), it looks like you're deleting an un-initialized bases pointer (array of pointers), or the actual pointers themselves are not being properly nullptr initialized.
This may be down to your sample code being incomplete however.
I'm using shared_ptr<Base> for some sort of tree list with derived classes. But I'm getting a pointer acces violation when my tree gets destructed.
My code looks something like this, besides, this actually similates my runtime error:
#include <iostream>
#include <memory>
#include <vector>
class Base;
typedef std::shared_ptr<Base> pBase;
class Derived;
class Base {
public:
std::vector<pBase> children;
pBase parent;
Base() {}
virtual ~Base() {}
virtual void doSomething() {}
void add(pBase i);
};
class Derived : public Base {
void doSomething() {
// Do something...
}
};
void Base::add(pBase i) {
i->parent = pBase(this);
children.push_back(i);
}
int main() {
pBase tree = pBase(new Derived());
pBase child(new Derived());
child->add(pBase(new Derived()));
tree->add(child);
}
Also when I add the following lines to Base::~Base:
std::cout << "destruct " << name << std::endl;
And implement a std::string called name in Base which is different for each instance, I can see that the destructor is called multiple times (because of the Base::parent reference I think). That ofcourse triggered my error, but I still don't understand why it happens because shared_ptr<Base> is expected to count its references before actually destroying it!!?
I hope some can tell me what I'm doing wrong!
But more important, how I can fix this!
Look at this line in add()
i->parent = pBase(this);
Each time you call add, you're creating a new shared pointer to this. These shared pointer are separate - that is, they are NOT 'shared' as you think. So, the first time you delete a child, it's parent gets deleted (because it's a shared pointer). Hence your code blows up.
Try (as a start) making parent a plain dumb pointer.
Base *parent;
Just to add to the others' answers: The canonical way to do what you want in the line
i->parent = pBase(this);
is to use std::enable_shared_from_this. You
Derive Base from it
class Base : std::enable_shared_from_this<Base> {
Ensure that every Base instance is owned by a std::shared_ptr. That is OK in your case, since you create the objects in expressions like
pBase child(new Derived());
Use shared_from_this() instead of this when you want a std::shared_ptr. The problematic line will then become
i->parent = shared_from_this();
Here
i->parent = pBase(this);
you create a smart pointer from a plain old pointer to an object which you didn't get directly from new. Never do this.
As #Roddy explained, you get separate smart pointer objects, with separate reference counters. Two reference counters for one pointee won't work.
In your case, it's probably ok to make parent a normal pointer, as #Roddy proposed. This way, you don't get in trouble with cyclic references. Just be sure that you never access the parent pointer after you deleted the parent. No problem if you delete all the children together with the parent (which happens automatically, unless you store more smart pointers to them, somewhere else)
If you want to initialize a smart pointer, you've got two choices, basically: Use smart pointers in every interface. Unfortunately that doesn't work for "this" because that's an implicit parameter. You would need to pass the smart pointer, which you already created, to the method manually, in an extra parameter. Like this:
tree->add(tree, child);
Which is kind of ugly, so you may want to consider making "add" a static method, so you won't need to pass the parent twice.
The other choice: Use another kind of smart pointer, like boost::intrusive_ptr, where you can store the reference count in the pointee. This way, you are able to find the reference count, even if you've got only a dumb pointer like "this".
Edit: The answer by #jpalecek, below, is better. Use that one. Sebastian.
I need to store a list of various properties of an object. Property consists of a name and data, which can be of any datatype.
I know I can make a class "Property", and extend it with different PropertySubClasses which only differ with the datatype they are storing, but it does not feel right.
class Property
{
Property(std::string name);
virtual ~Property();
std::string m_name;
};
class PropertyBoolean : Property
{
PropertyBoolean(std::string name, bool data);
bool m_data;
};
class PropertyFloat : Property
{
PropertyFloat(std::string name, float data);
float m_data;
};
class PropertyVector : Property
{
PropertyVector(std::string name, std::vector<float> data);
std::vector<float> m_data;
};
Now I can store all kinds of properties in a
std::vector<Property*>
and to get the data, I can cast the object to the subclass. Or I can make a pure virtual function to do something with the data inside the function without the need of casting.
Anyways, this does not feel right to create these different kind of subclasses which only differ by the data type they are storing. Is there any other convenient way to achieve similar behavior?
I do not have access to Boost.
C++ is a multi-paradigm language. It shines brightest and is most powerful where paradigms are mixed.
class Property
{
public:
Property(const std::string& name) //note: we don't lightly copy strings in C++
: m_name(name) {}
virtual ~Property() {}
private:
std::string m_name;
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const std::string& name, const T& data)
: Property(name), m_data(data);
private:
T m_data;
};
typedef std::vector< std::shared_ptr<Property> > property_list_type;
Edit: Why using std::shared_ptr<Property> instead of Property*?
Consider this code:
void f()
{
std::vector<Property*> my_property_list;
for(unsigned int u=0; u<10; ++u)
my_property_list.push_back(new Property(u));
use_property_list(my_property_list);
for(std::vector<Property*>::iterator it=my_property_list.begin();
it!=my_property_list.end(); ++it)
delete *it;
}
That for loop there attempts to cleanup, deleting all the properties in the vector, just before it goes out of scope and takes all the pointers with it.
Now, while this might seem fine for a novice, if you're an only mildly experienced C++ developer, that code should raise alarm bells as soon as you look at it.
The problem is that the call to use_property_list() might throw an exception. If so, the function f() will be left right away. In order to properly cleanup, the destructors for all automatic objects created in f() will be called. That is, my_property_list will be properly destroyed. std::vector's destructor will then nicely cleanup the data it holds. However, it holds pointers, and how should std::vector know whether these pointers are the last ones referencing their objects?
Since it doesn't know, it won't delete the objects, it will only destroy the pointers when it destroys its content, leaving you with objects on the heap that you don't have any pointers to anymore. This is what's called a "leak".
In order to avoid that, you would need to catch all exceptions, clean up the properties, and the rethrow the exception. But then, ten years from now, someone has to add a new feature to the 10MLoC application this has grown to, and, being in a hurry, adds code which leaves that function prematurely when some condition holds. The code is tested and it works and doesn't crash - only the server it's part of now leaks a few bytes an hour, making it crash due to being out of memory about once a week. Finding that makes for many hours of fine debugging.
Bottom line: Never manage resources manually, always wrap them in objects of a class designed to handle exactly one instance of such a resource. For dynamically allocated objects, those handles are called "smart pointer", and the most used one is shared_ptr.
A lower-level way is to use a union
class Property
union {
int int_data;
bool bool_data;
std::cstring* string_data;
};
enum { INT_PROP, BOOL_PROP, STRING_PROP } data_type;
// ... more smarts ...
};
Dunno why your other solution doesn't feel right, so I don't know if this way would feel better to you.
EDIT: Some more code to give an example of usage.
Property car = collection_of_properties.head();
if (car.data_type == Property::INT_PROP) {
printf("The integer property is %d\n", car.int_data);
} // etc.
I'd probably put that sort of logic into a method of the class where possible. You'd also have members such as this constructor to keep the data and type field in sync:
Property::Property(bool value) {
bool_data = value;
data_type = BOOL_PROP;
}
I suggest boost::variant or boost::any. [Related question]
Write a template class Property<T> that derives from Property with a data member of type T
Another possible solution is to write a intermediate class managing the pointers to Property classes:
class Bla {
private:
Property* mp
public:
explicit Bla(Property* p) : mp(p) { }
~Bla() { delete p; }
// The standard copy constructor
// and assignment operator
// aren't sufficient in this case:
// They would only copy the
// pointer mp (shallow copy)
Bla(const Bla* b) : mp(b.mp->clone()) { }
Bla& operator = (Bla b) { // copy'n'swap trick
swap(b);
return *this;
}
void swap(Bla& b) {
using std::swap; // #include <algorithm>
swap(mp, b.mp);
}
Property* operator -> () const {
return mp;
}
Property& operator * () const {
return *mp;
}
};
You have to add a virtual clone method to your classes returning a pointer to a newly created copy of itself:
class StringProperty : public Property {
// ...
public:
// ...
virtual Property* clone() { return new StringProperty(*this); }
// ...
};
Then you'll be able to do this:
std::vector<Bla> v;
v.push_back(Bla(new StringProperty("Name", "Jon Doe")));
// ...
std::vector<Bla>::const_iterator i = v.begin();
(*i)->some_virtual_method();
Leaving the scope of v means that all Blas will be destroyed freeing automatically the pointers they're holding. Due to its overloaded dereferencing and indirection operator the class Bla behaves like an ordinary pointer. In the last line *i returns a reference to a Bla object and using -> means the same as if it was a pointer to a Property object.
A possible drawback of this approach is that you always get a heap operation (a new and a delete) if the intermediate objects must be copied around. This happens for example if you exceed the vector's capacity and all intermediate objects must be copied to a new piece of memory.
In the new standard (i.e. c++0x) you'll be able to use the unique_ptr template: It
can be used inside the standard containers (in contrast to the auto_ptr which must not be used in the standard containers),
offers the usually faster move semantics (it can easily passed around) and
takes care over the held pointers (it frees them automatically).
I see that there are lots of shots at trying to solve your problem by now, but I have a feeling that you're looking in the wrong end - why do you actually want to do this in the first place? Is there some interesting functionality in the base class that you have omitted to specify?
The fact that you'd be forced to switch on a property type id to do what you want with a specific instance is a code smell, especially when the subclasses have absolutely nothing in common via the base class other than a name (which is the type id in this case).
Starting with C++ 17 we have something called as std::variant and std::any.
std::variant
An instance of std::variant at any given time either holds a value of one of its alternative types, or in the case of error - no value.
std::any
The class any describes a type-safe container for single values of any copy constructible type.
An object of class any stores an instance of any type that satisfies the constructor requirements or is empty, and this is referred to as the state of the class any object. The stored instance is called the contained object. Two states are equivalent if they are either both empty or if both are not empty and if the contained objects are equivalent.
The non-member any_cast functions provide type-safe access to the contained object.
You can probably do this with the Boost library, or you could create a class with a type code and a void pointer to the data, but it would mean giving up some of the type safety of C++. In other words, if you have a property "foo", whose value is an integer, and give it a string value instead, the compiler will not find the error for you.
I would recommend revisiting your design, and re-evaluating whether or not you really need so much flexibility. Do you really need to be able to handle properties of any type? If you can narrow it down to just a few types, you may be able to come up with a solution using inheritance or templates, without having to "fight the language".