Best strategy for manual memory management using smart pointers? - c++

Is there a recommended strategy for dealing with external libraries which expect manually managed raw pointers. For example a method which takes a vector of pointers:
ALibraryFunc(std::vector<ALibraryData*> p);
so generally you'd create your vector with something like:
std::vector<ALibraryData*> myVec;
for(...)
{
myVec.push_back(new ALibraryData(args));
}
//and then
ret = ALibraryFunc(myVec);
//and then
for(auto &a:myVec)
{
delete a;
}
myVec.clear();
I'd much prefer to use smart pointers but the library will not take them. This leaves me wondering if something like this is more stinky than just doing it manually:
std::vector<std::unique_ptr<ALibraryData>> myVecUP;
std::vector<ALibraryData*> myVec;
for(...)
{
myVecUP.push_back(std::make_unique<ALibraryData>(args));
myVec.push_back(myVecUP.back().get());
}
//and then
ret = ALibraryFunc(myVec);
myVec.clear();
myVecUP.clear();
The second version seems safer in case of exceptions or mistakes but it does risk dangling pointers. Am i missing something obvious here? What do/would you do?

You can declare a small class which will own the vector of raw pointers, and delete the pointers in the destructor:
struct VecOwner {
std::vector<ALibraryData*> vec;
VecOwner(<some arguments>)
{
// fill the vector here
}
~VecOwner()
{
for(auto &a:vec)
delete a;
vec.clear();
}
};
you should be able to reuse the class in all places where you use the library.

You can use 'scope exit' idiom :
//open scope block
{
std::vector<ALibraryData*> myVec;
////////////////////////////////////////
struct MyVecRAIICleaner{
std::vector<ALibraryData*> * myVecPtr;
~MyVecRAIICleaner(){
if (myVecPtr) {
for(auto& a: *myVecPtr)
delete a;
myVecPtr->clear();
}
}
} myRAIICleaner = {&myVec};
////////////////////////////////////////
for(...)
{
myVec.push_back(new ALibraryData(args));
}
//and then
ret = ALibraryFunc(myVec);
/** You needn't below code. */
////and then
//for(auto &a:myVec)
//{
// delete a;
//}
//myVec.clear();
}// end scope block
EDIT:
I'm sorry, but Wojtek Surowka's answer is not exception safe or required extra try catch block in constructor.

Related

Create new struct, insert into list, re-use pointer, return in vector... whether and how to delete?

In C++ code that I wrote to demonstrate an algorithm in an answer, I'm creating structs in a function using new, storing them in a list, moving them to a vector, then returning the vector:
struct my_struct {int a, b, c;};
std::vector<my_struct> myFunction(...) {
std::list<my_struct> my_list;
std::list<my_struct>::iterator current = my_list.begin();
std::vector<my_struct> my_vector;
my_struct *new_struct = nullptr;
while (...) {
...
if (!new_struct) {
new_struct = new my_struct;
new_struct->a = ...
}
...
if (new_struct) {
new_struct->b = ...
my_list.insert(current, *my_struct);
my_struct = nullptr;
}
...
if (...) {
current->c = ...
my_vector.push_back(*current);
current = my_list.erase(current);
}
...
}
return my_vector;
}
It compiles and seems to work correctly, however I'm more used to JavaScript and this code just feels like translated JavaScript; I'm specifically wondering whether I'm creating memory leaks, and whether I have to delete the structs in the calling function (and how).
Yes, you have a memory leak. If you invoke the new command, you will need to invoke a delete command in the future to free the memory allocated by new.
So, in this statement:
my_list.insert(current, *my_struct);
you are indeed copy the contents of *my_struct, not getting the ownership of it. So, in the following statement:
my_struct = nullptr;
You just got a memory leak.
To solve this, change your design to use smartpointer, for example, unique_ptr, or, better yet, dont use pointer at all, and just use a plain object:
my_struct new_struct;
As others in the question section have already pointed out, you probably shouldn't use new at all. The only reason to use pointers there at all is the if(newstruct) checks, if they are an essential part of your algorithm.
But if you use new, you should delete, too. It's safe to do that after inserting the struct into the list or vector - the list and vector contain copies.
Beginning with C++17, std::optional (and before that, boost::optional) is a sensible alternative solution for your specific problem here. It removes the need for pointers and the danger of memory leaks but at the same time still gives you a "nothing" state.
Your pseudo code would become something like:
// this is the correct way of defining a struct in C++:
struct my_struct {
int a;
int b;
int c;
};
std::vector<my_struct> myFunction(...) {
std::list<my_struct> my_list;
std::list<my_struct>::iterator current = my_list.begin();
std::vector<my_struct> my_vector;
std::optional<my_struct> new_struct; // new_struct does not hold a value
while (...) {
...
if (!new_struct.has_value()) { // if it does not hold a value...
new_struct = my_struct(); // it holds a value now (a default my_struct)
new_struct->a = ... // access syntax like a pointer
}
...
if (new_struct.has_value()) {
new_struct->b = ...
my_list.insert(current, *new_struct); // dereference syntax like a pointer
new_struct.reset(); // it no longer holds a value now
}
...
if (...) {
current->c = ...
my_vector.push_back(*current);
current = my_list.erase(current);
}
...
}
return my_vector;
}
Note how the syntax of std::optional deliberately mimics that of pointers.

Releasing memory of a struct containing multiple vectors

Having a struct such as:
struct PAIR {
vector<double> a;
vector<double> b;
};
Is using a function like the following a proper way to release the memory after defining and populating such a struct? If not, how do you deal with this situation?
void release(PAIR& p){
vector<double>().swap(p.a);
vector<double>().swap(p.b);
}
Isn't there a way to call some predefined/std function on PAIR itself to release memory?
Note that I'm not using new, etc. so definitions are simply like PAIR p;. Also, the struct is much more complex than just a pair of vectors that could have been defined using a std::pair.
All the related questions in SO on releasing memory for vectors are either about vectors themselves or vectors of a struct, not a struct containing multiple vectors. I'm looking for an elegant way to release memory used by such a struct.
Context
The vectors get really big, and I want to release the memory as soon as I can. But that lifetime/usability reaches in the middle of function! I don't want to spread the functionality in this function to multiple functions. These are pretty complicated computations and don't want to mess things up.
Given function does not release memory on the stack actually. It is approximately equivalent to
p.a.clear();
p.a.shrink_to_fit();
The vector itself remains in the memory (just with 0 elements).
Remember, any memory that was allocated on the stack (~ without the use of new) gets released only when the variable occupying this memory goes out of scope, not earlier.
So if you have a variable on the stack and want to delete it, you can just limit its scope:
struct PAIR {
vector<double> a;
vector<double> b;
};
int main()
{
// some stuff before...
{
PAIR p;
// some stuff with p object...
} // here p gets deleted (all memory gets released)
// some stuff after...
}
You mentioned new PAIR. With pointers it would look like this:
int main()
{
// some stuff before...
PAIR* p = new PAIR;
// some stuff with p object...
delete p; // here p gets deleted (all memory gets released)
// some stuff after...
}
Or as commentators requested:
int main()
{
// some stuff before...
{
auto p = std::make_unique<PAIR>();
// some stuff with p...
} // here p gets deleted (all memory gets released)
// some stuff after...
}
Is that what you wanted to achieve?
Does PAIR have to be a POD? Maybe something like this might work for you?
struct PAIR
{
private:
std::unique_ptr<std::vector<double>> aptr;
std::unique_ptr<std::vector<double>> bptr;
PAIR(const PAIR&) = delete;
public:
PAIR() : aptr(std::make_unique<std::vector<double>()),
bptr(std::make_unique<std::vector<double>()) {}
~PAIR() { release(); }
std::vector<double> &a = *aptr;
std::vector<double> &b = *bptr;
void release()
{
aptr.reset();
bptr.reset();
}
...
};
simply .resize(0) the vectors.

Appropriate destruction of certain class members

I have a class with several pointer members that can be reallocated. When I use the LoadOBJ() function, I'm supposed to replace the already held data but I'm having trouble with garbage collection. Below is some code.
class Object3d{
public:
int nVertex;
int nFace;
int nVertexNormal;
Vector3d *vertex;
Vector3d *vertexNormal;
Face3d *face;
void LoadOBJ(char*);
Object3d():nVertex(0), nFace(0), vertex(NULL), face(NULL){}
Object3d(char*);
~Object3d(){}
};
Face3d:
struct Face3d{
int nFaceV;
int *iVertex;
int *iVertexNormal;
Face3d():nFaceV(0){}
};
Everytime I load a new object with the LoadOBJ() function, I want to delete the previously allocated memory, rather than just use new and leak previously allocated memory.
I'm not sure how to do this. This is what I thought of for now:
void *vGarbage, *vGarbage2,
*fGarbage,
*iGarbage, *iGarbage2;
//nFace is the previous number of faces; in the case of a new object, it's 0
for(int i=0; i<nFace; i++)
{
iGarbage=face[i].iVertex;
iGarbage2=face[i].iVertexNormal;
delete[] iGarbage;
delete[] iGarbage2;
}
vGarbage=vertex;
fGarbage=face;
vGarbage2=vertexNormal;
delete[] vGarbage;
delete[] vGarbage2;
delete[] fGarbage;
The above code runs everytime I use LoadOBJ(), but there still is memory leak. I'm also wondering if this is the right way to do it?
To clarify where the problem/question is: why do I still have memory leak? And, is there better/cleaner way to delete the previously allocated memory?
Check out C++11's smart_pointers, they provide the ability of allocating memory which, when the object goes out of scope, will be freed automatically.
#include <memory>
#include <iostream>
struct Foo {
Foo() { std::cout << "Foo...\n"; }
~Foo() { std::cout << "~Foo...\n"; }
};
struct D {
void operator()(Foo* p) const {
std::cout << "Call delete for Foo object...\n";
delete p;
}
};
int main()
{
{
std::cout << "constructor with no managed object\n";
std::shared_ptr<Foo> sh1;
}
{
std::cout << "constructor with object\n";
std::shared_ptr<Foo> sh2(new Foo);
std::shared_ptr<Foo> sh3(sh2);
std::cout << sh2.use_count() << '\n';
std::cout << sh3.use_count() << '\n';
}
{
std::cout << "constructor with object and deleter\n";
std::shared_ptr<Foo> sh4(new Foo, D());
}
}
Output:
constructor with no managed object constructor with object Foo... 2 2
~Foo... constructor with object and deleter Foo... Call delete for Foo
object... ~Foo...
(http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr)
Remember that for each new a delete should be called when freeing memory. Local pointers can be dangerous if they get destroyed and you didn't free memory before that point.
The RAII paradigm in object-oriented C++ has been designed specifically to make resource management (and also memory management) easy.
If disaster has already been done, you can clean your code up with something like http://deleaker.com/ or equivalent memory leak-seeker software.
Also: if you can't use C++11 or you can't use a C++11-supporting compiler, take a chance of implementing smart pointers yourself, it shouldn't be too hard and will surely help your memory problems.
I understand you want to free the memory occupied by Object3d::vertex, Object3d::vertexNormal and Object3d::face before reasigning these members. First, you should provide a custom destructor for your Face3d so that you no longer need to care for it's members in the containing class. That is:
face3d::~face3d() {
if (iVertex) delete[] iVertex;
if (iVertexNormal) delete[] iVertexNormal;
}
In your Object3d class, you can use a dedicated clean-up function:
void Object3d::cleanup() {
if (face) delete[] face;
face = nullptr;
if (vertex) delete[] vertex;
vertex = nullptr;
if (vertexNormal) delete[] vertexNormal;
vertexNormal = nullptr;
nVertex = 0;
nFace = 0;
nVertexNormal = 0;
}
Btw, In the destructor Object3d::~Object3d() you must call that function as well.
This question might answer yours. I think that you have to cast the void pointer to a specific one, like int*, to make it work. But the behaviour is highly dependent of the compiler you use.
edit: the advice of using smart pointers is probably the easiest and safest way of solving your problem.
Use std::vector instead of manually managed arrays:
struct Face3d{
int nFaceV;
std::vector<int> iVertex;
std::vector<int> iVertexNormal;
Face3d():nFaceV(0){}
};
class Object3d{
public:
std::vector<Vector3d> vertex;
std::vector<Vector3d> vertexNormal;
std::vector<Face3d> face;
void LoadOBJ(char*);
Object3d():nVertex(0), nFace(0), vertex(NULL), face(NULL){}
Object3d(char*);
~Object3d(){}
};
This frees you from the burden to write destructors. As already said above, this is exemplifies the RAII pattern in C++ which should be used instead of manual resource management.
As a general comment, public data members are almost always a bad idea because it breaks encapsulation. Object3d should provide some services to clients and keep its internal private.

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).

Delete all items from a c++ std::vector

I'm trying to delete everything from a std::vector by using the following code
vector.erase( vector.begin(), vector.end() );
but it doesn't work.
Update: Doesn't clear destruct the elements held by the vector? I don't want that, as I'm still using the objects, I just want to empty the container
I think you should use std::vector::clear:
vec.clear();
EDIT:
Doesn't clear destruct the elements
held by the vector?
Yes it does. It calls the destructor of every element in the vector before returning the memory. That depends on what "elements" you are storing in the vector. In the following example, I am storing the objects them selves inside the vector:
class myclass
{
public:
~myclass()
{
}
...
};
std::vector<myclass> myvector;
...
myvector.clear(); // calling clear will do the following:
// 1) invoke the deconstrutor for every myclass
// 2) size == 0 (the vector contained the actual objects).
If you want to share objects between different containers for example, you could store pointers to them. In this case, when clear is called, only pointers memory is released, the actual objects are not touched:
std::vector<myclass*> myvector;
...
myvector.clear(); // calling clear will do:
// 1) ---------------
// 2) size == 0 (the vector contained "pointers" not the actual objects).
For the question in the comment, I think getVector() is defined like this:
std::vector<myclass> getVector();
Maybe you want to return a reference:
// vector.getVector().clear() clears m_vector in this case
std::vector<myclass>& getVector();
vector.clear() should work for you. In case you want to shrink the capacity of the vector along with clear then
std::vector<T>(v).swap(v);
vector.clear() is effectively the same as vector.erase( vector.begin(), vector.end() ).
If your problem is about calling delete for each pointer contained in your vector, try this:
#include <algorithm>
template< typename T >
struct delete_pointer_element
{
void operator()( T element ) const
{
delete element;
}
};
// ...
std::for_each( vector.begin(), vector.end(), delete_pointer_element<int*>() );
Edit: Code rendered obsolete by C++11 range-for.
Use v.clear() to empty the vector.
If your vector contains pointers, clear calls the destructor for the object but does not delete the memory referenced by the pointer.
vector<SomeClass*> v(0);
v.push_back( new SomeClass("one") );
v.clear(); //Memory leak where "one" instance of SomeClass is lost
Is v.clear() not working for some reason?
If you keep pointers in container and don't want to bother with manually destroying of them, then use boost shared_ptr. Here is sample for std::vector, but you can use it for any other STL container (set, map, queue, ...)
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
struct foo
{
foo( const int i_x ) : d_x( i_x )
{
std::cout << "foo::foo " << d_x << std::endl;
}
~foo()
{
std::cout << "foo::~foo " << d_x << std::endl;
}
int d_x;
};
typedef boost::shared_ptr< foo > smart_foo_t;
int main()
{
std::vector< smart_foo_t > foos;
for ( int i = 0; i < 10; ++i )
{
smart_foo_t f( new foo( i ) );
foos.push_back( f );
}
foos.clear();
return 0;
}
Adding to the above mentioned benefits of swap(). That clear() does not guarantee deallocation of memory. You can use swap() as follows:
std::vector<T>().swap(myvector);
If your vector look like this std::vector<MyClass*> vecType_pt you have to explicitly release memory ,Or if your vector look like : std::vector<MyClass> vecType_obj , constructor will be called by vector.Please execute example given below , and understand the difference :
class MyClass
{
public:
MyClass()
{
cout<<"MyClass"<<endl;
}
~MyClass()
{
cout<<"~MyClass"<<endl;
}
};
int main()
{
typedef std::vector<MyClass*> vecType_ptr;
typedef std::vector<MyClass> vecType_obj;
vecType_ptr myVec_ptr;
vecType_obj myVec_obj;
MyClass obj;
for(int i=0;i<5;i++)
{
MyClass *ptr=new MyClass();
myVec_ptr.push_back(ptr);
myVec_obj.push_back(obj);
}
cout<<"\n\n---------------------If pointer stored---------------------"<<endl;
myVec_ptr.erase (myVec_ptr.begin(),myVec_ptr.end());
cout<<"\n\n---------------------If object stored---------------------"<<endl;
myVec_obj.erase (myVec_obj.begin(),myVec_obj.end());
return 0;
}
class Class;
std::vector<Class*> vec = some_data;
for (unsigned int i=vec.size(); i>0;) {
--i;
delete vec[i];
vec.pop_back();
}
// Free memory, efficient for large sized vector
vec.shrink_to_fit();
Performance: theta(n)
If pure objects (not recommended for large data types, then just
vec.clear();