I'm trying to clear up my understanding of some memory issues in C++, primarily with containers containing pointers. Say I have something like this:
Header.H
#ifndef test_Header_h
#define test_Header_h
#include <vector>
using std::vector;
class ClassA {
int* intPtr;
public:
ClassA(int n);
~ClassA();
};
class ClassB {
vector<ClassA*> vecPtr;
public:
ClassB();
~ClassB();
void someFunc();
};
#endif
main.cpp
#include <iostream>
#include "Header.h"
int main(int argc, const char * argv[])
{
ClassA objA(5);
ClassB objB;
return 0;
}
ClassA::ClassA(int n) {
intPtr = new int[n];
}
ClassA::~ClassA() {
delete intPtr;
}
ClassB::ClassB() {
vecPtr = vector<ClassA*>(0);
}
ClassB::~ClassB() {
//no destructor needed
}
void ClassB::someFunc() {
//vecPtr = something using new;
int* testPtr = new int[vecPtr.size()];
//do stuff
delete testPtr;
}
Does vecPtr ever need to be deleted? Or does the destructor of ClassA accomplish this for me? Also, if instead of having a vector, would it be the same situation if I had used a list of pointers or a pair? Finally, for clarification testPtr needs to be deleted in someFunc because that is the scope it was declared in, so putting it in the destructor would be pointless. If testPtr shared the address the address of an important member, deleting it would also the important member? I know there is quite a few questions but I think I'm just going around in a circular argument in my head, confusing myself more and more.
vecPtr does not need to be deleted, because it is not a pointer. This might be different for the pointers in vecPtr and depends on who has the ownership for those pointers.
Yes, testPtr must be deleted, where it is available. Anything else won't even compile. If you point testPtr to a member and delete that, you will likely see a double free or corruption error when the member would be deleted on the destructor.
In general where something must be deleted is up to the implementation. The only thing that you need to look out for is that every new gets exactly one delete from somewhere in any code path. Usually constructors/destructor are therefore a good place.
You have big problems here. Remember this:
1) any new must be balanced with a delete.
2) any new[] must be balanced with a delete[].
In fact, if you mix them (as you've done), you have undefined behaviour. Boom! You need to write delete[] intPtr; and delete[] testPtr;
Also and simply put, you don't write delete vecPtr since you didn't write new vecPtr.
Internally, the C++ runtime remembers the number of elements that you've allocated using new[]. You need to use delete[] to allow that runtime to access that information.
Related
all.
Suppose we have pointer to a struct, which has a member that is a dynamic array (among other members).
I can free all the objects but want your opinion on the best practice for this specific situation. See the code below, that compiles and runs without segmentation fault:
#include <iostream>
struct TestStruct
{
int a; // And other members here
int *b = new int[10];
~TestStruct()
{
}
};
int main(void)
{
struct TestStruct *a_struct = new TestStruct();
// Do something with the struct
delete[] a_struct->b;
delete a_struct;
return 0;
}
This way I am assuming the memory is returned properly. However, if I move any of these deletes to the destructor, there will be segfault. That is, if I move the array deletion to the destructor (delete[] a_struct->b;), it is no longer accessible because I deleted the pointer to the struct before (delete a_struct;), and vice-versa, and memory leak happens.
After reading this thread C++ free all memory used by struct, it is a bit inconclusive because most of the suggestions are taken for granted to work, but there is segfault in many of them.
I have simplified the problem since the array I will use is 3D. If it is not possible to free 100% of the memory in the destructor, then I am ready to use a method just to run the loops to free the array memory and the pointer to the struct. So I want to know your take on this specific situation.
Since you are using C++ and dynamic arrays, std::vector, std::array, or, e.g., std::unique_ptr are all better ways of handling this than working with new directly.
The proper, RAII way to this would be:
struct TestStruct
{
int a; // And other members here
int *b = new int[10];
~TestStruct()
{
delete[] b;
}
};
int main(void)
{
struct TestStruct *a_struct = new TestStruct();
delete a_struct;
return 0;
}
Proper design wouldn't allow multiple deletion by same pointer filed. If such risk exist, you can assign nullptr to pointer. deletion of null pointer is noop.
RAII (Resource acquisition is initialization) essentially boils down to: who allocated memory is one who deallocates.
In the destructor, delete only dynamically allocated members, but not the object itself (this is done in the course of destruction).
So the following code should be fine:
struct TestStruct
{
int a; // And other members here
int *b = new int[10];
~TestStruct() {
delete[] b;
}
};
int main(void)
{
struct TestStruct *a_struct = new TestStruct();
// Do something with the struct
delete a_struct;
return 0;
}
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.
Alright so Say I have a class with all its definition, bla bla bla...
template <class DT>
class Foo{
private:
DT* _data;
//other stuff;
public:
Foo(DT* data){ _data = data; }
virtual ~Foo(){ delete _data; }
//other methods
};
And then I have in the main method:
int main(){
int number = 12;
Foo<anyRandomClass>* noPrimitiveDataObject = new Foo<anyRandomClass>(new anyRandomClass());
Foo<int>* intObject = new Foo<int>(number);
delete noPrimitiveDataObject; //Everything goes just fine.
delete intObject; //It messes up here, I think because primitive data types such as int are allocated in a different way.
return 0;
}
My question is: What could I do to have both delete statements in the main method work just fine?
P.S.: Although I have not actually compiled/tested this specific code, I have reviewed it extensively (as well as indented), so if you find a mistake, please be nice.
You're taking the address of a literal and then calling delete on it later, which is wrong. It was not allocated with new, therefore you cannot deallocate it with delete (nor would it make any sense to).
If you had written new int(12) instead it would be ok, however, there are other problems.
First, your class violates The Rule of Three. What happens if I copy intObject and then call delete on both of them? You end up calling delete on the same pointer twice.
Second, why are you allocating these things dynamically to begin with? You create an RAII style wrapper to handle deallocation for you... and then proceed to allocate it manually. What problem is that solving?
I suppose this is an exercise for you, and that's great. Just remember what problem you're trying to solve with this code.
If I am using a std::vector<T> I am certainly not going to use it like this:
std::vector<int> *v = new std::vector<int>;
It defeats the entire purpose of using a vector! Now I have to manually manage this pointer/memory, and that's the problem that the vector class (and other RAII style classes) were created to solve.
So, to use it properly, you do this:
void foo()
{
std::vector<int> v;
// do stuff with v
// it allocates its memory dynamically so you don't have to.
// when we exit the function the destructor is called, the memory
// deallocated, and life continues as it should.
}
Use automatic storage duration to your advantage, that's the whole point. Also be very clear about who owns the memory. If it is not clear from your class design who owns a given chunk of memory then it is not safe to delete it in your destructor.
Ok, you changed the code to this now:
int number = 12;
// ...
Foo<int>* intObject = new Foo<int>(number);
Same problem; you are taking the address of a variable allocated with automatic storage duration and then calling delete on it. This is wrong. Anything you allocate with new you deallocate with delete, but nothing else. Ever. That's it.
It seem like you didn't know you can do new int(12). So for example you could change your code to the following:
Foo<int>* intObject = new Foo<int>(new int(12));
(I'm assuming this is just for learning, as not using new altogether would be better).
Also, I just noticed your code is wrong, perhaps you wanted the following:
Foo(DT* data){ _data = data; }
virtual ~Foo(){ delete _data; }
Side Note
Before posting a question, at least try to compile your examples.
I had made a header file with a class named cmysqldb with a lot of pointers.
My problem is now this:
How could i create a destructor that will delete the pointers that may cause potential memory leak?
here is the header code:
#ifndef CMSYQLDB_H
#define CMSYQLDB_H
#include <QMultiMap>
#include <QStringList>
#include "mysql.h"
class cmysqldb
{
public:
cmysqldb::~cmysqldb()
{
const char *text,
MYSQL *connection,
MYSQL_RES *result,
MYSQL_RES *fresult,
MYSQL_FIELD *mfield
}
int query_state;
int numfields;
MYSQL mysql;
MYSQL_ROW row;
MYSQL_ROW fieldrow;
....
};
#endif // CMSYQLDB_H
is this what you mean???
Resources acquired through new should be deallocated using delete and with new[] should be with delete[]. As simple as that to avoid memory leaks. Could be more helpful if you post more specific code.
Destructor bears the same name of the class, except that it has a ~ symbol before it.
cmysqldb :: ~cmysqldb()
{
// deallocate the resources with the above mentioned rule
}
class foo
{
int var ;
int *ptr ;
public:
foo()
{
ptr = new int ;
}
~foo()
{
delete ptr ;
}
};
void bar()
{
foo obj ;
// .....
} // <-- obj goes out of scope and it's destructor is called at this point.
foo class has two member variables var, ptr of type int, int* respectively. So, bytes required to hold an integer in var and pointer(ptr) that can point to an integer's address is automatically allocated. These resources are not allocated by us. So, it's not our responsibility to deallocates these resources. So far so good.
ptr = new int ;
new int acquires resources from the free store that can hold an int and it's address is returned which ptr holds. Now, this acquisition of resource from free store is because of the new operation defined by the user. So, it's the job of the user to return the resources back to the free store. So, the statement in the destructor -
delete ptr ;
Get a book from The Definitive C++ Book Guide and List which can even explain better. Also follow #Michael advice of using smart pointers which manages resources automatically.
In order to delete the pointers, you will need to store them somewhere. It is unclear where you do this (you don't have fields for all the pointer parameters accepted by the constructor), so I won't be able to give you exactly the code to do this, but I will lay out how you can go about doing this.....
To declare the destructor, add the following to your class declaration:
~cmysqldb();
Note that if your class will have any virtual methods, you should instead declare it as:
virtual ~cmysqldb();
And in your source file add:
cmysqldb::~cmysqldb()
{
// contents of your destructor goes here.
}
Now, how exactly you free your resources depends on how they were allocated. If you used some library-specific create function and there is a library-specific free function, then use that. If it was allocated using malloc, then use free; if it was allocated with new, use delete; if it was allocated using new[], then use delete[]. Also, you should use smart pointer classes such as boost::scoped_ptr (std::unique_ptr) or boost::shared_ptr (std::shared_ptr), wherever possible to avoid explicitly managing these resources via new/delete in your constructors / destructors.
One last, very important point... whenever you have a function that accepts a pointer, it is very important that you document the ownership semantics. Is it owned by the caller? Is ownership transferred? Etc.
A memory leak occurs when you acquire dynamic memory using new or new[] & do not deallocate the memory using delete or delete[]`.
Your constructor declaration is of the type:
cmysqldb(const char *text, MYSQL *connection, MYSQL_RES *result,
MYSQL_RES *fresult, MYSQL_FIELD *mfield);
You should keep a track of whatever dynamic memory allocations you are doing in the constructor with new and new[]and you should deallocate all of them with a corresponding delete or delete[].
The best thing to do would be to use smart pointers to store all the pointers to related objects. C++ will automatically call destructors of all sub-objects when the parent object is destroyed.
And if your parent object fails partly constructed, its destructor won't be called. So any pointers already allocated would leak if you design things to be freed in the destructor. However, subobjects destructors get run if the subobject was allocated, so by using smart pointers this partly allocated case is taken care of for you.
For more information, look up RAII (Resource Acquisition Is Initialization).