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.
Related
I seem to have an issue with dynamic memory allocation.
Below you'll see a derived class that contains a pointer for a name variable that will be dynamically allocated using the void name(const char* name) method. The function is run by the Product constructor, which sets a name for the product class when the object is created. Here's the class:
namespace sict {
class Product :public Streamable {
char* name_;
public:
Product(const char* name);
virtual ~Product();
void name(const char* name);
}
And here's the name function itself, along with the one argument constructor:
void sict::Product::name(const char * name) {
int g = strlen(name);
name_ = new char[g];
strncpy(name_, name, g);
name_[g] = 0;
}
Product::~Product() {
delete [] name_;
name_ = nullptr;
}
To me this code seems capable enough of created the object then destroying it peacefully whenever it exits the scope of the function it's running in. However, when the function ends and the destructor runs, the program freezes/crashes at delete [] name_. Running the program on Visual Studio's compiler seems to yield no particular errors (other than the program freezing), but the gcc compiler detects some sort of heap corruption. Would anybody know why this is happening?
I'm not sure why Sean Cline didn't post his comment as an answer, but Sean is correct.
name_ is given g elements and then name_[g] is set to zero, but name_[g] is one past the end of the array. Either use name_ = new char[g+1]; or name_[g-1] = 0; so that you don't go past the end of the array.
Also, as several comments point out, any time you have a class that allocates memory dynamically, make sure you define the copy constructor, the assignment operator, and the destructor. If you miss one, the default implementation will perform a shallow copy, which can cause headaches for you.
A shallow copy is when the pointer is copied instead of the data it points to. In your case, if an object of this class is ever copied or assigned, you end up with two objects pointing to the same data on the heap, and they would both try to delete it when they run their destructors.
For more information on those functions, see the Rule of Three
Let's say I have the following code which, in short, has:
a BaseClass with a pointer to a PointerClass
a ChildClass that inherits from BaseClass
a HolderClass that has an std::vector of ChildClasss and an std::vector of BaseClass*s:
The entire code is as follows:
#include <stdlib.h>
#include <time.h>
#include <vector>
class PointerClass {
public:
int num;
double num2;
PointerClass() {
srand(time(NULL));
num = rand() % 100;
num2 = rand() % 100 / 2.0;
}
};
class BaseClass {
public:
PointerClass *pointerClass;
};
class ChildClass: public BaseClass {
public:
ChildClass() {
pointerClass = new PointerClass();
}
};
class HolderClass {
public:
std::vector<BaseClass*> basePointerVec;
std::vector<ChildClass> childVec;
HolderClass() {
}
void addParentClass() {
ChildClass childClass = ChildClass();
childVec.push_back(childClass);
basePointerVec.push_back(&childClass);
}
};
int main(int argc, const char * argv[]) {
HolderClass holderClass = HolderClass();
for (int count = 0; count < 20; count++) {
holderClass.addParentClass();
}
for (int count = 0; count < holderClass.basePointerVec.size(); count++) {
delete holderClass.basePointerVec[count]->pointerClass;
}
return 0;
}
My problem is, after adding a pointer to the ChildClass into the std::vector<BaseClass*> basePointerVec and the actual ChildClass into the std::vector<ChildClass> childVec in the addParentClass() method in HolderClass, the data in basePointerVec andchildVec are completely different.
Furthermore, when I try to free the PointerClasses from the childVec, everything works fine. But when I try to free them from the basePointerVec instead, I get an error telling my I'm trying to free a pointer I have not allocated memory for.
And sure enough, when I use breakpoints to inspect everything, I find some funky behavior. It seems that every time I call ChildClass childClass = ChildClass(); in addParentClass(), every pointer in basePointerVec gets changed to point to the newly created ChildClass's BaseClass.
The point of me doing this in my actual program is to take advantage of polymorphism and have multiple classes inherit from BaseClass.
So my question is, why is every pointer in the vector being changed to point to the newly created class and how can I fix it?
P.S. sorry for the length of this question, it's as short as I could possibly make it
childVec.push_back(childClass);
The push_back method of the class vector copies the object. So the added object is not the same as childClass in this case.
You can't delete the pointers from basePointerVec because they were not allocated with new but they were allocated locally and they are deleted at the end of addParentClass. So, the code of addParent is wrong because the pointer you push in the vector is no longer valid after the end of the method and may cause segmentation faults(in best case). Here is a suggestion of improvement:
void addParentClass() {
ChildClass* childClass = new ChildClass();
childVec.push_back(*childClass);
basePointerVec.push_back(childClass);
}
The memory is now allocated dynamically, you should make sure to free these pointers with delete.
EDIT:
void addParentClass() {
childVec.push_back(ChildClass());
basePointerVec.push_back(&childVec.back());
}
And if you are using C++11:
void addParentClass() {
childVec.emplace_back();
basePointerVec.push_back(&childVec.back());
}
The other answers already addressed the specific problem in your code. Here are two general points about your program above that will help you IMHO avoid all sorts of problems in the future:
When you define a class, esp. one which can be subclassed, always make the dtor public virtual except if you have a specific reason not too.
Always store resources in classes with the RAII principle:
Except for a good reason, you should never have a naked member pointer. Use a shared_ptr member instead.
Except for a good reason, you should never have a vector of naked pointers. Again use a vector of shared pointers.
Using this, hopefully, you won't need to track in your head what got destroyed when before something was copied to whatever, etc. It will make it harder to mix up heap objects and stack objects.
Look here:
void addParentClass() {
ChildClass childClass = ChildClass();
childVec.push_back(childClass);
basePointerVec.push_back(&childClass);
}
Your objects are not allocated on the heap. They are values and in basePointerVec you put their addresses (which don't make sense anyway after addParentClass() returns). Don't try to delete those, that will crash your program. They will be automatically deleted when childVec goes out of scope.
When addParentClass returns, the childClass object is destroyed. Therefore, the pointer to that object, that you put into basePointerVec cannot be used anymore.
You are creating a local variable that is destroyed as soon addParentClass goes out of scope. Also see the answers to this question which explains what happens when you don't use new. So the vector of BaseClass pointers are pointing to an object that is destroyed, and the childVec vector of objects are creating new copies when you use push_back, from this page:
The new element is initialized as a copy of value.
This is why the two vectors are pointing to different objects. You could create a destructor for the classes and add debugging prints to the destructor and the constructor to see when the objects are created/destroyed, this should give you a better idea of what is happening in what order.
In the past I always created a map like this:
class TestClass
{
private:
std::map<int,int> *mapA;
};
TestClass::TestClass
{
mapA = new std::map<int,int>();
}
TestClass::~TestClass
{
mapA->clear(); // not necessary
delete mapA;
}
So, now I read all over the place at Stackoverflow: avoid pointers as often as possible
Currently I want to create the map without pointer and new (no need to delete the object by myself and less danger of getting some memory leak)!
class TestClass
{
public:
TestClass() : mapA() // this is also needed?
{};
private:
std::map<int,int> mapA;
};
Any further steps for correct creation of the map necessary?
Thanks for any help and/or clarification!
Nope that's it, and you don't need to explicitly initialize it in the constructor.
As zennehoy says, it is not necessary to initialize the map in the TestClass constructor.
Let me note a difference between the two implementations:
In the first one, the TestClass, as it is currently written, is not copyable without undesirable effects because the raw pointer to the dynamically allocated map is copied:
TestClass *A = new TestClass; // A has a map
TestClass *B = new TestClass(A); // B shares the map with A!
delete A; // this deletes A's map (in destructor)
delete B; // this deletes A's map again! wrong
In your second implementation, that does not happen because the map, and not just its address, is copied completely.
To solve that issue in your first implementation, you should use a shared pointer, or do the work yourself by implementing the operator= and the copy constructor. Or, if you want to really share the map between copied instances, you should implement a reference counting mechanism.
Inside a method can one create an uninitialised object from the class?
Here's some context: imagine a class where the constructors all allocate memory:
class NumberArray
{
size_t m_Size;
int *m_Numbers;
public:
NumberArray() { m_Size = 1; m_Numbers = new int[1]; m_Numbers[0] = 0; }
// . . . other methods for manipulating or constructing . . .
~NumberArray() { delete[] m_Numbers; }
// What if I had a method that concatenates two arrays?
NumberArray ConcatenateWith(const NumberArray &) const;
};
Inside such a method one would desire to create an uninitialised object of class NumberArray, and then 'construct' a new object based on this and the object in the parameter? AKA:
NumberArray NumberArray::ConcatenateWith(const NumberArray &other) const
{
// Mystery manner of creating an uninitialised NumberArray 'returnObject'.
returnObject.m_Size = m_Size + other.m_Size;
returnObject.m_Numbers = new int[returnObject.m_Size];
std::copy(m_Numbers, m_Numbers + m_Size, returnObject.m_Numbers);
std::copy(other.m_Numbers, other.m_Numbers + other.m_Size, returnObject.m_Numbers + m_Size);
return returnObject;
}
What's the best way of doing this? Basically, I don't want the default constructor to create a size 1 array that I will just delete and then allocate a new array for again anyway.
It's not entirely clear what you are trying to do, but if all you want is to create a new instance of the class and not have a constructor other than the default constructor called then do just that.
All you have to do is create a private constructor, that has a different signature from the default constructor and which does not allocate memory (or differs in whatever way you need it to differ from the default constructor); then simply have your class invoke that constructor internally, when necessary.
What you're asking for is placement new. This looks something like this:
#include <cstdlib>
#include <new>
void* mem = std::malloc(sizeof(T)); // memory for a T (properly aligned per malloc)
T* x = new (mem) T; // construct a T in that memory location
x->~T(); // destruct that T
std::free(mem); // and free the memory
Doing this correctly (in an exception-safe manner with properly managed and aligned memory) is not a trivial task. You need to be careful about the lifetime of your objects.
For your question, you are describing exactly what std::vector does. It allocates raw uninitialized memory and constructs inserted elements directly into that memory. And lots of its code is dedicated to just getting the lifetime and memory management correct and exception safe!
You should strongly prefer to use std::vector instead of writing it yourself.
There is no well-defined way, as far as I'm aware, to create an object without invoking it's constructor. This is regardless of whether you have access to its public interface or not, though you could implement a private or protected constructor if you want to restrict who can invoke it. There is otehrwise no restrictions on creating new instances of a class from its own internal methods, in fact it is quite common to define a private constructor and a static public method that create instances of said object if you want to restrict under which conditions said object can be created.
If you want to, you can allocated sufficient memory for an object and reinterpret_cast a pointer to that memory to a pointer of the type you want. This usually works for POD's, but since many implementations (if not all) of polymorphic inheritance in c++ adds a pointer to a vtable to polymorphic instances this approach will usually, if not always, fail for those.
In short, create a private constructor and have a static method invoke it and then do any other work that you need is my recommendation.
I think this may be similar to what you want, an 'anonymous' class of sorts:
struct test {
virtual void doSomething() {
puts("test");
}
};
struct a {
test *t() {
struct b : test {
void doSomething() {
puts("b");
};
};
return new b;
};
};
int main()
{
a a;
a.t()->doSomething(); // outputs 'b'
}
However, due to slicing and how new works on C++, you must return a pointer and the 'anonymous' type must have a name, even if it's restricted only to the function.
If you could edit the OP and clarify exactly what you wish to accomplish by this, maybe we could help you more.
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.