I am using borland 2006 c++, and have following code. I am using vectors, and have trouble understanding why the destructor is not being called.
basically i have a class A
class A
{
private:
TObjectList* list;
int myid;
public:
__fastcall A(int);
__fastcall ~A();
};
__fastcall A::A(int num)
{
myid = num;
list = new TObjectList();
}
__fastcall A::~A()
{
delete list;
}
int main(int argc, char* argv[])
{
myfunc();
return 0;
}
void myfunc()
{
vector<A*> vec;
vec.push_back(new A(1));
vec.push_back(new A(2));
}
according to what i read, when variable vec goes out of scope in myfunc(), it should destruct its contained elements, so the destructor for A should be called. I have a breakpoint at ~A(), but never gets called, i have tried resize(), erase methods also
TIA
vec does destruct its elements when it goes out of scope. The problem here is that vec's elements are the pointers to A objects, not A objects themselves. If you instead did
vector<A> vec;
vec.push_back(A(1));
vec.push_back(A(2));
...then things would work as you expect.
ETA: note, though, that if you do this you have to define a copy constructor for A. That should involve doing a deep copy of the TObjectList member. Otherwise, when you copy an A object you'll wind up with two objects both pointing to the same TObjectList, and your program will crash when the second object is destroyed.
The destructor for A isn't called because you don't have a vector of A. You have a vector of pointers to A, and the destructors for the pointers are called. Pointers don't have a destructor, so nothing happens.
One way to delete everything would be to manually do something like
while (!vec.empty())
{
delete vec.back();
vec.pop_back();
}
Lots of good answers already, but I'll add one more:
Use boost::ptr_vector from the Boost Pointer Container Library, instead of std::vector. It will delete the objects when the vector goes out of scope, thus calling the destructors.
Grab the Boost libraries, and wherever you have a raw pointer in the above you use boost::shared_ptr<> instead. (Well, not in the signature of main().)
Related
(Before anyone asks: no, i didn't forget the delete[] statement)
I was fiddling around with dinamically allocated memory and i run into this issue. I think the best way to explain it is to show you these two pieces of code I wrote. They are very similar, but in one of them my class destructor doesn't get called.
// memleak.cpp
#include <vector>
using namespace std;
class Leak {
vector<int*> list;
public:
void init() {
for (int i = 0; i < 10; i++) {
list.push_back(new int[2] {i, i});
}
}
Leak() = default;
~Leak() {
for (auto &i : list) {
delete[] i;
}
}
};
int main() {
Leak leak;
while (true) {
// I tried explicitly calling the destructor as well,
// but this somehow causes the same memory to be deleted twice
// and segfaults
// leak.~Leak();
leak = Leak();
leak.init();
}
}
// noleak.cpp
#include <vector>
using namespace std;
class Leak {
vector<int*> list;
public:
Leak() {
for (int i = 0; i < 10; i++) {
list.push_back(new int[2] {i, i});
}
};
~Leak() {
for (auto &i : list) {
delete[] i;
}
}
};
int main() {
Leak leak;
while (true) {
leak = Leak();
}
}
I compiled them both with g++ filename.cpp --std=c++14 && ./a.out and used top to check memory usage.
As you can see, the only difference is that, in memleak.cpp, the class constructor doesn't do anything and there is an init() function that does its job. However, if you try this out, you will see that this somehow interferes with the destructor being called and causes a memory leak.
Am i missing something obvious? Thanks in advance.
Also, before anyone suggests not using dinamically allocated memory: I knwow that it isn't always a good practice and so on, but the main thing I'm interested in right now is understanding why my code doesn't work as expected.
This is constructing a temporary object and then assigning it. Since you didn't write an assignment operator, you get a default one. The default one just copies the vector list.
In the first code you have:
Create a temporary Leak object. It has no pointers in its vector.
Assign the temporary object to the leak object. This copies the vector (overwriting the old one)
Delete the temporary object, this deletes 0 pointers since its vector is empty.
Allocate a bunch of memory and store the pointers in the vector.
Repeat.
In the second code you have:
Create a temporary Leak object. Allocate some memory and store the pointers in its vector.
Assign the temporary object to the leak object. This copies the vector (overwriting the old one)
Delete the temporary object, this deletes the 10 pointers in the temporary object's vector.
Repeat.
Note that after leak = Leak(); the same pointers that were in the temporary object's vector are also in leak's vector. Even if they were deleted.
To fix this, you should write an operator = for your class. The rule of 3 is a way to remember that if you have a destructor, you usually need to also write a copy constructor and copy assignment operator. (Since C++11 you can optionally also write a move constructor and move assignment operator, making it the rule of 5)
Your assignment operator would delete the pointers in the vector, clear the vector, allocate new memory to hold the int values from the object being assigned, put those pointers in the vector, and copy the int values. So that the old pointers are cleaned up, and the object being assigned to becomes a copy of the object being assigned from, without sharing the same pointers.
Your class doesn't respect the rule of 3/5/0. The default-generated move-assignment copy-assignment operator in leak = Leak(); makes leak reference the contents of the temporary Leak object, which it deletes promptly at the end of its lifetime, leaving leak with dangling pointers which it will later try to delete again.
Note: this could have gone unnoticed if your implementation of std::vector systematically emptied the original vector upon moving, but that is not guaranteed.
Note 2: the striked out parts above I wrote without realizing that, as StoryTeller pointed out to me, your class does not generate a move-assignment operator because it has a user-declared destructor. A copy-assignment operator is generated and used instead.
Use smart pointers and containers to model your classes (std::vector<std::array<int, 2>>, std::vector<std::vector<int>> or std::vector<std::unique_ptr<int[]>>). Do not use new, delete and raw owning pointers. In the exceedingly rare case where you may need them, be sure to encapsulate them tightly and to carefully apply the aforementioned rule of 3/5/0 (including exception handling).
Taking a look to the following code snippet:
//A.h
class A
{
void f();
};
//A.cpp
#include "A.h"
void A:f()
{
map<string, string> *ThisMap = new map<string, string>;
//more code (a delete will not appear)
}
//main.cpp
#include "A.h"
int main( int argc, char **argv )
{
A object;
object.f();
//more code (a delete will not appear)
return 0;
}
When main() ends it execution, object will be destroyed. Would be destroyed dinamic allocated memory asigned to ThisMap too?
Would be destroyed dinamic allocated memory asigned to ThisMap too?
No!
You have a memory leak, since object gets destroyed, its destructor gets called, but no delete is called for your map.
Pro-tip: delete whatever you new'ed, when you are done with it.
PS: I highly doubt it that you need to dynamic allocate a standard container (like std::map), but if you really are sure that you need to use, then consider using std::unique_ptr.
Would be destroyed dinamic allocated memory asigned to ThisMap too?
No, the rule of thumb before C++11 was that if you new something, you must delete it later.
Since C++11, you are very strongly encouraged to use smart pointers, which deal with allocation/deallocation for you in a safe manner. std::unique_ptr's documentation is a good starting point.
No.
1. If you want ThisMap to be A's data field, you have to declare and implement your own destructor, so your code should be like:
class A
{
std::map<std::string, std::string> *ThisMap;
void f();
~A();
};
void A::f()
{
ThisMap = new map<std::string, std::string>;
//more code (a delete will not appear)
}
A::~A()
{
if(ThisMap) delete ThisMap;
}
2. If ThisMap is just a function variable, so you just have to delete it at the end of the use, like:
void A::f()
{
map<string, string> *ThisMap = new map<std::string, std::string>;
//more code (a delete will not appear)
delete ThisMap;
}
Notice that its A::f and not A:f
:)
I am new to C++ in VS C++. I'm creating win32 dll library. I have a major basic problem with try finally block.
Let's pretend I have something like this:
class object {
private:
int* foo;
public:
object() : foo(new int()) { *foo = 42; }
~object() {
// Now since foo is dynamically allocated, the destructor
// needs to deallocate it
delete foo;
}
};
int main() {
vector<object*> tmp;
tmp.push_back(new object());
// Do some stuff with tmp
for (int i = 0; i < tmp.size(); ++i) {
delete tmp[i]; // Calls ~object (which deallocates tmp[i]->foo)
// and deallocates *tmp[i]
}
tmp.clear();
return 0;
}
I have copied the code snippet from:
Another stackoverflow question
In the above example, how can I use the "free" part so that it could be always freed up as the method finishes its job? I thought try finally should suffice.
But now I can see that there are several: try, __try Don't know what is the difference. With __try I get compiler errors which says something about RAII ...
Could anyone help me with this?
It's Resource Acquisition Is Initialization, RAII for short. The idea there being that if an object owns a resource, its destructor should free it automatically. In all of these cases, with C++11 you'd want to use std::unique_ptr instead of raw pointers. So, for instance:
class object {
std::unique_ptr<int> foo;
public:
object() : foo(std::make_unique<int>(42)) { }
// no destructor necessary here
};
int main() {
std::vector<std::unique_ptr<object>> tmp;
tmp.push_back(std::make_unique<object>());
// when tmp goes out of scope, each object in it will already
// be deleted for you, no code necessary
}
Of the many advantages here is the fact that now you don't have to worry about writing the copy constructor for object (as-is, your foo will get deleted twice if you copy it). See also Rule of Zero
There are various ways.
One is to make the vector<object *> a vector<unique_pointer<object> >. No need to explicitly deallocate the objects at all.
Another is to place the vector<object *> a member of another class that manages the deallocation. So, when an instance of that class is destroyed, its destructor releases all the elements of the vector in your code. You will need to supply other constructors and member functions for that class, to manage adding objects to the vector properly.
Suppose I have a class similar to the following:
#include <vector>
class element
{
public:
element();
~element();
virtual void my_func();
private:
std::vector<element*> _elements;
};
How would I go about implementing the destructor?
I was thinking something like this, but I'm not sure. I am worried about memory leaks since I'm relatively new to C++.
void element::destroy()
{
for(int i = 0; i < _elements.size(); ++i)
_elements.at(i)->destroy();
if(this != NULL)
delete this;
}
element::~element()
{
destroy();
}
Thank you.
PS:
Here is a sample main:
int main()
{
element* el_1 = new element();
element* el_2 = new element();
element* el_3 = new element();
el_1.add_element(el_2);
el_2.add_element(el_3);
return 0;
}
Also, what if I do this (aka don't use new):
int main()
{
element el_1;
element el_2;
element el_3;
el_1.add_element(&el_2);
el_2.add_element(&el_3);
return 0;
}
element::~element()
{
typedef std::vector<element*>::const_iterator iterator;
for (iterator it(_elements.begin()); it != _elements.end(); ++it)
delete *it;
}
delete this in a destructor is always wrong: this is already being destroyed!
In addition, you would need to declare a copy constructor and copy assignment operator (either leaving them undefined, making your class noncopyable, or providing a suitable definition that copies the tree).
Alternatively (and preferably), you should use a container of smart pointers for _elements. E.g.,
std::vector<std::unique_ptr<element>> _elements;
When an element is destroyed, its _elements container will be automatically destroyed. When the container is destroyed, it will destroy each of its elements. A std::unique_ptr owns the object to which it points, and when the std::unique_ptr is destroyed, it will destroy the element to which it points.
By using std::vector<std::unique_ptr<element>> here, you don't need to provide your own destructor, because all of this built-in functionality takes care of the cleanup for you.
If you want to be able to copy an element tree, you'll still need to provide your own copy constructor and copy assignment operator that clone the tree. However, if you don't need the tree to be copyable, you don't need to declare the copy operations like you do if you manage the memory yourself: the std::unique_ptr container is itself not copyable, so its presence as a member variable will suppress the implicitly generated copy operations.
class element
{
public:
element();
~element();
private:
std::vector<element*> _elements;
};
Per the Rule of Three, this lacks the definition of copy constructor and assignment operator.
element::~element()
{
destroy();
}
Calling delete this (which is what destroy() does) from a destructor is always wrong, because the destructor is what is called when the current object is being deleted.
for(int i = 0; i < _elements.size(); ++i)
_elements.at(i)->destroy();
While this does the job of calling delete on the objects you call destroy() for, this arrangement has the disadvantage that you must not destroy such objects other than through calling destroy(). In particular, this
element el_1;
will be a problem, because e1_1 will be automatically destroyed when it falls out of scope bay calling its destructor. Since this calls destroy(), which invokes delete this on an object not allocated using new, this causes Undefined Behavior. (If you are lucky it blows up into your face right away.)
It would be far better to remove the delete this from the destructor, and only have the destructor delete the objects in the object's vector:
for(std::vector<element*>::size_type i = 0; i < _elements.size(); ++i)
delete _elements[i];
if(this != NULL)
delete this;
Checking a pointer for NULLness is never necessary, because delete is defined to do nothing when the pointer passed to it is NULL.
The delete this shouldn't be there, as the object is already under destruction by definition.
If you copy an element then all the pointers within its member vector are copied too; then when the original goes out of scope their pointees are destroyed, and the element copy has a vector of dangling pointers. You need a copy ctor and assignment operator.
So, just this basic start has already created two very serious faults. This is a sign that the design is to be avoided. It doesn't appear to be all that clear what the ownership semantics are to the programmer who uses it.
Why is dynamic allocation required here at all? Why not store elements objects themselves?
#include <vector>
class element
{
public:
void add_element(element const& e) {
_elements.push_back(e);
}
private:
std::vector<element> _elements;
};
This will change your program subtly if you previously had multiple references to the same element going into different other elements, but you'll have to decide for yourself whether that tangled mess of dependencies is something you need.
Nope, it doesn't work that way. You never delete this. You just don't. Basically, take out your destroy method, put everything into ~element() except for the delete this part. And instead of calling the destroy method, just delete _elements[i];.
I have come across an interesting problem. I have a function in C++ that returns a vector filled with classes. Once the vector is returned, it calls deconstructors for each class that is element in the vector.
The problem is an obvious one: the data is destroyed where a class points to the pointers, which get released when the object is destroyed. I can only assume the deconstructors are called because the vector is on the stack, and not on the heap.
So the question is:
Is there anyway to keep returning vector from a function, without it being destroyed? Or would I have to either pass a pointer to return vector as an input to the function?
You can create anything on heap with new. You shouldn't give out from the function the references to your stack objects, as they will be destroyed as soon as the function finishes.
If you prefer your function to return the vector by value, be sure that the objects inside the vector implement copy constructor (and perhaps assignment operator, too, not sure about that). Having that, please do not forget about the Rule of Three.
C++11 should solve your problem using rvalue references. Honestly, I haven't tried it myself, but from what I read it will do exactly what you are trying to do, return the vector without destroying and recreating it (by passing the memory allocated by that vector on to the new vector instead of having the new vector create its own memory and copy the contents over from the old one).
C++ vectors are allocated on the heap. When you return a vector by value a new one will be created with copies of all the elements, then the original elements will be destroyed.
It sounds like you haven't defined your copy constructors properly. For example:
class ThisIsWrong
{
public:
ThisIsWrong()
{
i = new int;
*i = rand();
}
~ThisIsWrong()
{
delete i;
i = nullptr;
}
int value() const
{
return *i;
}
private:
int* i;
};
void foo()
{
vector<ThisIsWrong> wronglets;
wronglets.push_back(ThisIsWrong());
return wronglets;
}
void main()
{
vector<ThisIsWrong> w = foo();
w[0].value(); // SEGFAULT!!
}
You either need to delete the copy and assignment constructors (which will then turn this into a compilation error instead of runtime), or implement them properly.