stl + memory management question - c++

For example, i have next code:
#include <set>
using namespace std;
struct SomeStruct
{
int a;
};
int main ()
{
set<SomeStruct *> *some_cont = new set<SomeStruct *>;
set<SomeStruct *>::iterator it;
SomeStruct *tmp;
for (int i = 0 ; i < 1000; i ++)
{
tmp = new SomeStruct;
tmp->a = i;
some_cont->insert(tmp);
}
for (it = some_cont->begin(); it != some_cont->end(); it ++)
{
delete (*it);
}
some_cont->clear(); // <<<<THIS LINE
delete some_cont;
return 0;
}
Does "THIS LINE" need to be called before deleting some_cont for avoiding memory leaks or destructor will be called automatically?

You don't need to call it, destructor will be called for sure.

No, there is no need to clear the set before destroying it.
Note that there is very rarely a need to allocate an std::set (or any standard container) manually. You'd be much better off just putting it in automatic storage and letting C++ handle the cleanup for you:
So instead of
set<SomeStruct *> *some_cont = new set<SomeStruct *>;
use
set<SomeStruct *> some_cont;
then change all some_cont-> to some_cont. and remove the delete some_cont (the container will be destroyed when main exits automatically.
The advantage to do things this way are:
You don't need to remember to delete the container, and
You don't need to do an expensive memory allocation up front.
It's also far more idomatic C++ to put things in automatic storage.

No, you don't need to explicitly clear a set before destroying the set.
OTOH, you do have a number of other problems ranging from lousy (Java-like) design, to incorrect syntax, to a missing operator to lots of potential memory leaks. While some of the design might make sense in Java or C#, it's a really poor idea in C++. Once we get rid of the most egregious problems, what we have left is something like this:
#include <set>
struct SomeStruct
{
int a;
SomeStruct(int i) : a(i) {}
bool operator<(SomeStruct const &other) const { return a < other.a; }
};
int main ()
{
std::set<SomeStruct> some_cont;
for (int i = 0 ; i < 1000; i ++)
{
SomeStruct tmp(i);
some_cont.insert(tmp);
}
return 0;
}

No it is not, this will be done automatically in the set's destructor.

The STL containers automatically free any memory they own. So in your case the place allocated to store your SomeStruct* will be freed by the destructor of set. Note that the destructor of set does not call any destructors of SomeStruct, so it's good you iterate over them to delete them yourself.

Related

Deleting dynamic array in C++ causes an error

I have a class called Myclass. In the main function, I have created an array object for this class. Whenever I try to delete this dynamically allocated array, the visual studio will say, Error: Debug Assertion Failed!. Expression: is_block_type_valid(header->_block_use). Can you please tell me what is causing this or show me an example of fixing this issue.
#include <iostream>
using namespace std;
class Myclass
{
public:
void print()
{
cout << "Hello from Myclass" << endl;
}
};
int main()
{
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
// Call each object's print function.
for (int index=0; index < 3; index++)
{
obj[index]->print();
}
delete[] obj; //Error
return 0;
}
This:
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
is not a dynamically allocated array. It is an array with automatic storage, holding pointers to dynamically allocated objects. To properly clean up, you need:
delete obj[0];
delete obj[1];
delete obj[2];
Because every new must be matched with a delete, and you can only delete via delete[] something that was allocated via new[].
There is no need for any dynamic allocation here, just do:
Myclass obj[3] = {};
The delete[] operator should only be used for arrays created using the new[] operator, which your obj isn't. You have a fixed array of pointers to objects, each of which must be deleted as such:
for (int index=0; index < 3; index++)
{
delete obj[index];
}
Alternatively, you can create your object array using the new[] operator, then delete the array with delete[]:
int main()
{
Myclass* obj = new Myclass[3];
// Call each object's print function.
for (int index = 0; index < 3; index++) {
obj[index].print(); // Note: Use "." here, not "->"
}
delete[] obj;
return 0;
}
The variable obj is declared as an array with automatic storage duration with the element type Myclass *.
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
That is it is an array of pointers not a pointer.
Each element of the array is indeed a pointer that points to a dynamically allocated memory. So as the array contains three elements you need to call the operator delete three times for each element.
It is simpler to do that in the range-based for loop.
For example
for ( auto &item : obj )
{
delete item;
item = nullptr;
}
I think you allocated the array wrong.
You should write Myclass* obj = new Myclass[3];
The above answer is perfect.
I would only add this is not a good style code, if you "think in C++". This is a rather C style code.
First of all, when you are coding in C++ and is not obligued to use C-compatible code, be cautious whenever you see yourself using a C pointer.
In this case, if instead of using a C array of C pointers, you had used a std::vector of MyClass objects, the vector destructor would have called your class destructor for each element, which I think is what you wanted.
My suggestion: change the C array to std::vector and you will be happier. Look how you could have implemented it, using C++11 features and forgetting old C stuff:
#include <iostream>
using namespace std;
#include <vector>
class Myclass
{
public:
void print()
{
cout << "Hello from Myclass" << endl;
}
};
int main()
{
cout<<"Hello World" << endl;
vector<Myclass> obj(3);
// Call each object's print function.
for (auto instance : obj)
{
instance.print();
}
return 0;
}
In this case you don't even need to worry about deleting the objects, since the vector destructor will be called when the function goes out of scope, and it will take care of calling Myobjects' destructors. Much cleaner and safer code.
Or, in case performance is a very bottleneck for you and you need a static array, if you are using C++11 or later, you also can use std::array, a less "wild" option (https://en.cppreference.com/w/cpp/container/array).
So that is the tip I leave for you, if coding in C++, use the best this language can offer, and try to forget dangerous and wild old C features. C is good as a lightweight and simpler language, when you need it. But everyone knows it is dangerous (and you have just stumbled on it).
This book of the Bjarne focuses on teaching C++ from scratch, leaving behind the not always productive C legacy:
Programming: Principles and Practice Using C++

Do I need to call delete[] on a member array that is declared with a constant value in class decleration?

here is an example of a code hopefully will demonstrate my confusion
#define MAX_LENGTH 5
class Bar
{
private:
Foo *_myFooArray[MAX_LENGTH];
public:
Bar()
{
for (int i = 0; i < MAX_LENGTH; ++i)
{
_myFooArray[i] = new Foo(i);
}
}
};
Since I am not creating the array with new I don't think I can use delete[] but what if I want to delete the objects that are allocated dynamicly? do I iterate through the array and delete them one at a time? as such;
~Bar()
{
for (int i = 0; i < MAX_LENGTH; ++i)
{
delete _myFooArray[i];
}
}
I will probably hear some of you screaming at me Use Vectors!! I appreciate that. I just want to learn. Just for completeness, If for some reason I have to use the array as mentioned above, are there anything that I need to pay extra attention besides deleting the array correctly?
One of the rules in C++ when not using smart pointers is "every new needs a delete."
You must use the destructor from your question to avoid leaking memory. The array itself is not allocated using new so you do not need to delete it.
No, you do not delete [] the array. The array is part of your instance's data. The elements you allocate specifically are not, so you should delete them.

Memory leak prevention C++ (Am I right or wrong?)

I have searched the internet for hours and hours and came up with these steps to prevent memory leaks (w/o use of smart pointers and advance tools as such). Please let me know if there are any issues with any of the below findings... Thanks in advance.
for each new there should be a delete.
if the new is inside a class putting the delete in the destructor would take care of the dynamically allocated memory.
if you do a new object obj from class foo in main then in you would have to explicitly delete obj.
if you have multi-dimentional dynamic arrays you have to delete both levels. (I am a bit unsure of this being safe... I thought just one delete for the ptr might do it but after thinking harder I figured it is a dynamic array of dynamic arrays and should treat each as a dynamic array separately).
ex 1.
char *ptr;
ptr = new char[size];
// Some Code here
delete ptr;
ex 2.
//foo.h
class foo {
private:
char * ptr;
public
foo();
~foo();
};
// foo.cpp
foo::foo()
{
ptr = new char[100];
for (int i = 0; i < 100; i++)
ptr[i] = i;
}
foo::~foo()
{
delete ptr;
}
ex 3.
//main.cpp foo class stays the same as ex 2.
int main()
{
foo obj = new foo();
// Some code here
delete obj;
return 0;
}
ex 4.
//foo.h
class foo {
private:
char ** ptr;
public
foo();
~foo();
};
//foo.cpp
foo::foo()
{
ptr = new char[100];
for (int i = 0; i < 100; i++)
ptr[i] = new char[100];
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
ptr[i][j] = i;
}
foo::~foo()
{
for (int i = 0; i < 100; i++)
delete ptr[i];
delete ptr;
}
Below are some tips you need to take care while managing memory on your own:-
First and most important of all is:-
1) Always use delete with new and delete[] with new[].Mixing these would result in undefined behavior.
2) Never combine malloc/delete OR new/free.
For your question "if you have multi-dimentional dynamic arrays you have to delete both levels."
Yes you have to take care of them.
Things you mentioned are correct i.e you have to explicitly delete the memory whenever you are allocating memory in heap. Though you missed one important aspect which revolves around RAII. Let's say there's a function in which you are taking care of allocation/deallocation.
void fun ()
{
1) int* ptr;
2) ptr = new int; //allocated memory.
3) ... //do something with ptr.
4) delete ptr; //done with ptr now delete it.
}
Now you are doing good by deleting memory which you allocated using new. However, there could be a chance that program execution won't even reach to your delete. ( in case exception is thrown in STEP#3). That case would constitute a memory leak.
To care of these issues we have smart pointers based on the concept of RAII. They will automatically delete the memory they are referring to whenever go out of scope that means you don't need to take care of memory management.
for each new there should be a delete.
Yes. And to be more precise: Every new must have a matching delete, and every new[] must have a matching delete[]
if the new is inside a class putting the delete in the destructor would take care of the dynamically allocated memory.
No! You also should take care on what should happen for copies through copy constructor or assignment, unless you explicitly forbid these operations. See What is The Rule of Three? for more details.
if you do a new object obj from class foo in main then in you would have to explicitly delete obj.
?? See 1.?
if you have multi-dimentional dynamic arrays you have to delete both levels. (I am a bit unsure of this being safe... I thought just one delete for the ptr might do it but after thinking harder I figured it is a dynamic array of dynamic arrays and should treat each as a dynamic array separately).
Yes, you always have to take care about proper memory management, if you're using raw pointers, no matter how many levels of indirection.
My final advice is, leave your head clean about bothering with such questions, but use the stuff provided with the <memory> smart pointers, and standard c++ containers.
Don't use new/delete directly, unless you're a 100% sure what you're doing, and you're a 200% sure you really need to do it.
As you're asking about actual issues:
(ex 2.) The delete doesn't match the new char[]
ptr = new char[100];
// ^^^^^
foo::~foo() {
delete [] ptr;
// ^^ put the square brackets there
}
same for (ex 4.)

Memory of a variable or object automatically terminated of finish at the end of program than why we use destructor?

In the following program we are creating Circle object in local scope because we are not using new keyword. We know that memory of a variable or object automatically terminated of finish at the end of program than why we use destruct?
#include<iostream>
using namespace std;
class Circle //specify a class
{
private :
double radius; //class data members
public:
Circle() //default constructor
{
radius = 0;
}
void setRadius(double r) //function to set data
{
radius = r;
}
double getArea()
{
return 3.14 * radius * radius;
}
~Circle() //destructor
{}
};
int main()
{
Circle c; //defalut constructor invoked
cout << c.getArea()<<endl;
return 0;
}
Assuming memory as an infinite resource is VERY dangerous. Think about a real-time application which needs to run 24x7 and listen to a data feed at a high rate (let' say 1,000 messages per second). Each message is around 1KB and each time it allocates a new memory block (in heap obviously) for each message. Altogether, we need around 82 GB per day. If you don't manage your memory, now you can see what will happen. I'm not talking about sophisticated memory pool techniques or alike. With a simple arithmetic calculation, we can see we can't store all messages in memory. This is another example that you have think about memory management (from both allocation and deallocation perspectives).
Well, first of all, you don’t need to explicitly define a destructor. One will automatically be defined by the compiler. As a side note if you do, by the rule of the 3, or the 5 in c++11 if you declare any of the following: copy constructor, copy assignment, move constructor (c++11), move assignment (c++11) or destructor you should explicitly define all of them.
Moving on. Oversimplified, the RAII principle states that every resource allocated must be deallocated. Furthermore, over every resource allocated must exist one and only one owner, an object responsible for dealocating the resource. That’s resource management. Resource here can mean anything that has to initialized before use and released after use, e.g. dynamically allocated memory, system handler (file handlers, thread handlers), sockets etc. The way that is achieved is through constructors and destructors. If your object is responsible of destroying a resource, then the resource should be destroyed when your object dies. Here comes in play the destructor.
Your example is not that great since your variable lives in main, so it will live for the entirely of the program.
Consider a local variable inside a function:
int f()
{
Circle c;
// whatever
return 0;
}
Every time you call the function f, a new Circle object is created and it’s destroyed when the function returns.
Now as an exercise consider what is wrong with the following program:
std::vector foo() {
int *v = new int[100];
std::vector<int> result(100);
for (int i = 0; i < 100; ++i) {
v[i] = i * 100 + 5;
}
//
// .. some code
//
for (int i = 0; i < 100; ++i) {
result.at(i) = v[i];
}
bar(result);
delete v;
return result;
}
Now this is a pretty useless program. However consider it from the perspective of correctness. You allocate an array of 100 ints at the beginning of the function and then you deallocate them at the end of the function. So you might think that that is ok and no memory leaks occur. You could’t be more wrong. Remember RAII? Who is responsible for that resource? the function foo? If so it does a very bad job at it. Look at it again:
std::vector foo() {
int *v = new int[100];
std::vector<int> result(100); <-- might throw
for (int i = 0; i < 100; ++i) {
v[i] = i * 100 + 5;
}
//
// .. some code <-- might throw in many places
//
for (int i = 0; i < 100; ++i) {
result.at(i) = v[i]; <-- might (theoretically at least) throw
}
bar(result); <-- might throw
delete v;
return result;
}
If at any point the function throws, the delete v will not be reached and the resource will never be deleted. So you must have a clear resource owner responsible with the destruction of that resource. What do you know the constructors and destructors will help us:
class Responsible() { // looks familiar? take a look at unique_ptr
private:
int * p_ = nullptr;
public:
Responsible(std::size_t size) {
p_ = new int[size];
}
~Responsible() {
delete p_;
}
// access methods (getters and setter)
};
So the program becomes:
std::vector foo() {
Responsible v(100);
//
// .. some code
//
return result;
}
Now even if the function will throw the resource will be properly managed because when an exception occurs the stack is unwinded, that is all the local variables are destroyed well... lucky us, the destructor of Responsible will be invoked.
Well, sometimes your object can have pointers or something that needs to be deallocated or such.
For example if you have a poiner in you Circle class, you need to deallocate that to avoid memory leak.
Atleast this is how i know.

Would this be considered good C++ code

I have a vector with raw pointers (no, I cannot use smart pointers) and I want to add items to the list in a for loop. I've made a little trial project, and I wondered if this is considered good C++ code in terms of pointer management.
Please only consider raw pointer management, I am not interested in smart pointers for this particular problem I'm trying to solve.
A simple object:
class Request
{
public:
std::string name;
};
std::vector<Request*> requests;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = new Request();
req->name = s;
requests.push_back(req);
}
EDIT:
So the problem I am trying to solve is adding the DOMNode* to a vector from this library.
I'm starting to get the feeling that trying to write a wrapper for the parts I need from this library for my project, is a bad idea. Or maybe the library is no good?
I haven't got it to work properly using smart_ptr, if anybody out there has, then I'd like to hear about it.
Well, this leaks memory, so it is bad. Can you use a Pointer Container?
The reason this code leaks is because you create objects on the heap using new, but you never call delete on them.
As for you comment, if you have an object that manually manages some resource, you need The Big Three.
I'll consider that you have a loop, at the end of the method, to call delete on each member of the vector.
There are still issues, specifically exception safety issues.
If anything throws between the creation of the Request and its registration in the vector, you've lost the memory. One solution is to temporarily use a scoped_ptr to hold on the memory, push_back with ptr.get() and then call the release method since now the memory is owned by the vector.
If anything throws between the point when you have created the items in the vector and the point you destroy them, you need to catch the exception, destroy the items, and then rethrow.
There might be others, but RAII has been invented for a reason, it's really difficult to do without (correctly...)
If you cannot use smart pointers, then use boost::ptr_vector.
Note that if you are using TinyXml, memory management in XmlNode is probably dictated by the library - recent history iirc is that many of your problems are associated with properly understanding the memory ownership and release paradigm for this library.
What memory management do I need to cleanup when using TinyXml for C++?
What is the best open XML parser for C++?
If you are not able (or allowed) to use smart pointers, probably you could make use of a simple memory manager like this:
template <class T>
class MemManager
{
public:
typedef std::vector<T*> Vec;
~MemManager ()
{
size_t sz = v_.size ();
for (size_t i = 0; i < sz; ++i)
delete v_[i];
}
T* pushNewObject ()
{
T* t = NULL;
try
{
t = new T;
if (t != NULL)
v_.push_back(t);
}
catch (std::bad_alloc& ex) { /* handle ex */ }
return t;
}
const Vec& objects() const { return v_; }
private:
Vec v_;
};
// test
{
MemManager<Request> mm;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = mm.pushNewObject();
req->name = s;
}
} // all Request objects will be deleted here when
// the MemManager object goes out of scope.
A quick improvement could be to derive a class RequestVector from std::vector<Request*>, add a ClearRequests method (which deletes all the Request objects and clears the vector) and and make it's destructor call ClearRequests.
(Actually aggregating the vector in RequestVector could be a better choice, but a derived class is faster done).