deallocating gsl vectors in structs - c++

Can you explain what's going on with my code here? I'm not sure if I'm using the destructor correctly or not in the struct.
With the destructor in there I get:
function1: 23
function2: 8.86183e-317
* glibc detected ./a: double free or corruption (fasttop): 0x000000000111b010 **
If I just comment out the destructor I get:
function1: 23
function2: 24
which is what I want. But don't I need the destructor to avoid a memory leak for a more complicated program?
(As you can see I may be a bit confused on pointers/allocation in general)
Thanks!
Edit: oh yeah, and why does the extra allocation step in function1 make a difference?
Edit2: Should I be initializing x = 0 in the constructor? I thought that was proper...should I be allocating it on initialization when I do this? So instead: x = gsl_vector_alloc(1).
#include <iostream>
using namespace std;
#include <cassert>
#include <cmath>
#include <gsl/gsl_vector.h>
struct struct1{
gsl_vector * x;
struct1() {
x = 0;
}
~struct1() {
if (x) gsl_vector_free(x);
}
};
void function1(void *p) {
struct1 s = *(struct1 *) p;
s.x = gsl_vector_alloc(1);
gsl_vector_set(s.x, 0, 24);
}
void function2(void *p) {
struct1 s = *(struct1 *) p;
gsl_vector_set(s.x, 0, 24);
}
int main() {
struct1 s;
s.x = gsl_vector_alloc(1);
gsl_vector_set(s.x, 0, 23);
function1(&s);
cout << "function1: " << gsl_vector_get(s.x, 0) << endl;
function2(&s);
cout << "function2: " << gsl_vector_get(s.x, 0) << endl;
return 0;
}

Inside of function1 and function2 you make a copy of the struct1 object that you create in the main() function. These copies have the same pointer x. When the destructor for each of these copies is called, gsl_vector_free is called, so you try to call it three times on the same pointer:
once in function1 when s is destroyed
once in function2 when s is destroyed
once in main when s is destroyed
You need to implement a copy constructor and copy assignment operator for this class. Any time you have a class that owns a resource, you need to implement these two functions and a destructor. A resource is anything that needs to be cleaned up when you are done using it.
In your sample code, it would be far better to encapsulate all of the allocation and deallocation inside of the class so that you can use the class without worrying about it. Make the class actually manage its resource.

Related

Do I need to call the destructor of vector in this scenario

Now I implement a class and I need to use vector to hold some pointers.This is a global member.
vector g_vIPControlCollection;
When the system finalize. I want to reclaim the memory. Then I define the destroy method.
void Destroy()
{
int size = g_vIPControlCollection.size();
if (size > 1)
{
for (int i = 0; i < size; i++)
{
g_vIPControlCollection[i]->Release();
}
}
g_vIPControlCollection.clear();
g_vIPControlCollection.~vector<IPersistorControl*>(); //Does this line is necessary?
}
My question is whether I need to call destructor of the vector? Thanks in advance. Your help will be greatly appreciated.
No.
If you did that, after the call to Destroy it would be left in an invalid state. It will self destruct when its owner gets destroyed.
And your Destroy function should probably be a destructor, too.
No you should not, what you should do is use a unique_ptr to manage your IPersistorControl objects for example:
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
struct Point{
int x; int y;
Point(int x,int y): x(x), y(y){}
~Point(){ cout<< "destroying " << y<<endl;}
};
int main() {
{
vector<unique_ptr<Point>> ps;
ps.emplace_back(unique_ptr<Point>(new Point(1,2)));
ps.emplace_back(unique_ptr<Point>(new Point(1,3)));
ps.emplace_back(unique_ptr<Point>(new Point(1,4)));
} // will call dtors here
cout << "Example 1" <<endl;
{
vector<unique_ptr<Point>> ps;
ps.emplace_back(unique_ptr<Point>(new Point(1,2)));
ps.emplace_back(unique_ptr<Point>(new Point(1,3)));
ps.emplace_back(unique_ptr<Point>(new Point(1,4)));
ps.clear(); // will call them here
cout << "Example 2" <<endl;
}
return 0;
}
Note that if IPersistorControl is some object that needs a special type that requires some other method of "reclaiming" (e.g windows handles or file handles) you can specify a Deleter e.g:
unique_ptr<FILE, int(*)(FILE*)> filePtr(fopen("LALA.txt", "wb"), fclose);
^ ^
Deleter type the actual Deleter
No you should almost never call the destructor explicitly.
What you need to do here is just g_vIPControlCollection.clear(); that you are already doing. After this std::vector hardly keeps any memory (typically 12 bytes on 32 bit machines) and would be cleaned when the program ends.
No. You shouldn't and needn't call destructor manually. That would
result in destructor invocation two times ( 1 by you and 1 when
object goes out of scope), affecting object state and your program
might crash at best. See live demo
It is good and recommended practice to clear memory allocated. But since it is a
global object, and program is going to terminate, even if you don't
free memory, it will reclaimed as process terminates.
Try using std::unique_ptr<> for storing pointers in std::vector
so that memory will be released when the clear method in
invoked on std::vector. This way you don't have to iterate and manually invoke the Release method of each member of std::vector

Does using .reset() on a std::shared_ptr delete all instances

I'm new to shared_ptr's and I'm trying to figure out the exact functionality of the .reset() function.
#include <memory>
#include <stdio>
using namespace std;
class SomeClass{};
int main()
{
shared_ptr<SomeClass> sp (nullptr);
//do some stuff, sp now has 10 co-owners
cout << sp.use_count << endl;
sp.reset();
cout << sp.use_count << endl;
return 0;
}
Would output
10
0
So since I used the reset function are all instances deleted from memory? As in, have I just eliminated any possible memory leaks with sp? Obviously this was a toy example that I quickly made up, sorry if it has any errors.
Follow up situation:
shared_ptr<SomeClass> returnThis() {
shared_ptr<SomeClass> someObject(new SomeClass(/*default constructor for example*/) );
return someObject;
}
somehere in main:
shared_ptr<SomeClass> mainObject;
mainObject = returnThis();
Does mainObject have a use count of 2 because someObject was created in a function but never cleared? Or is it one and the clean-up is done automatically when returning the value?
When you use .reset(), you are eliminating one owner of the pointer, but all of the other owners are still around. Here is an example:
#include <memory>
#include <cstdio>
class Test { public: ~Test() { std::puts("Test destroyed."); } };
int main()
{
std::shared_ptr<Test> p = std::make_shared<Test>();
std::shared_ptr<Test> q = p;
std::puts("p.reset()...");
p.reset();
std::puts("q.reset()...");
q.reset();
std::puts("done");
return 0;
}
The program output:
p.reset()...
q.reset()...
Test destroyed.
done
Note that p and q are both owners of the object, and once both p and q are reset, then the instance is destroyed.
No.
The whole purpose of shared_ptr is that you cannot delete it from one place if someone is using it in another. shared_ptr::reset() just decreases use_count by one and replaces its object by nullptr.
The .reset() method only applies to the object it's called upon.
It just replaces the pointer that variable is holding.

Using smart_ptr for user defined class objects

As a C++ neophyte trying to understand smart pointers. I have written below code to check.
It did compile and run but I was expecting the destructor of my class to be invoked and print the cout's from the destructor but it didn't .
Do we need to overload any function in the user defined class so that its destructor is called when the smart_ptr object of that class gets destroyed.
Why is that it did not invoke the object destructor. What is that i am missing?
#include <iostream>
#include <cstdlib>
#include <tr1/memory>
#include <string>
//using namespace std;
class myclass
{
public:
myclass();
myclass(int);
~myclass();
private:
int *ptr;
std::string *cptr;
};
myclass::myclass()
{
std::cout << "Inside default constructor\n";
}
myclass::myclass(int a)
{
std::cout << "Inside user defined constructor\n" ;
ptr = new int[10];
cptr = new std::string("AD");
}
myclass::~myclass()
{
std::cout << "Inside destructor..\n";
delete [] ptr;
delete cptr;
std::cout << "Freed memory..\n";
}
int main()
{
int i;
std::cin >> i;
std::tr1::shared_ptr<std::string> smartstr(new std::string);
std::tr1::shared_ptr<myclass> smart_a(new myclass(i));
if(i == 0)
{
std::cout << "Exiting...\n";
exit(-1);
}
}
The reason the object is never destroyed is because you are exiting the program by calling exit. This causes the program to exit before the smart pointer objects have a chance to go out of scope thus the objects they manage are never destroyed. Since you are in main use a return statement instead of calling exit.
And, as additional information to other answers, note from the Standard:
Per ยง3.6.1/4:
Terminating the program without leaving the current block (e.g., by
calling the function std::exit(int) (18.5)) does not destroy any
objects with automatic storage duration (12.4).
In the code below,
if(i == 0)
{
std::cout << "Exiting...\n";
exit(-1);
}
You are terminating the program by calling exit(), so the object is never destroyed. So remove the exit(-1); from the code.
One possible solution is ensure that your buffer is flushed in your destructor. Use std::endl; in your destructor. For more information, please look here: Buffer Flushing, Stack Overflow

Boost Shared Pointer Constructors/Destructors

I'm trying to implement smart pointers in my code. I've created a class to convert a Point to a shared_ptr and I've added a print function for the shared_ptr. In my main, I create an array of shared_ptr of type Shape. When I assign Points to the array, I only see raw constructors/destructors, rather than the shared constructor/destructors. Is this code correct?
Thanks.
#include "Point_H.hpp"
#include "Shape_H.hpp"
#include "Array_H.hpp"
#include "boost/shared_ptr.hpp"
using namespace CLARK::Containers;
using namespace CLARK::CAD;
class P1
{
private:
boost::shared_ptr<Point> pp;
public:
P1(boost::shared_ptr<Point> value) : pp(value) { cout << "P1 constructor call (default)" << endl; }
virtual ~P1() { cout << "P1 destructor call" << endl; }
void print() const { cout << "Point: " << *pp << endl; }
};
void Print()
{
boost::shared_ptr<Point> myPoint (new Point);
{
P1 point1(myPoint);
point1.print();
}
}
int main()
{
// Typedef for a shared pointer to shape
// a typedef for an array with shapes stored as shared pointers.
typedef boost::shared_ptr<Shape> ShapePtr;
typedef Array<ShapePtr> ShapeArray;
ShapeArray my_ShapeArray(3);
ShapePtr my_Point (new Point(3.1459, 3.1459));
my_ShapeArray[0] = my_Point;
my_ShapeArray[0]->Print();
return 0;
}
The output looks like the below (the constructor/destructor statements are from the Point/Shape/Array classes themselves, rather than from the code in this source file.
Array constructor call
Shape constructor call (default)
Point constructor call (3.1459,3.1459) ID:41
Point destructor call
Shape destructor call
Array destructor call
I was expecting to see shared_ptr constructor/destructor statements. Is my problem in the P1 code or in my implementation in the main or elsewhere?
Thanks!
You're calling
my_ShapeArray[0]->Print();
which must be a member function of Shape.
You are not calling the
Print();
function which you define in the code given and which is the one using the P1 class.
You aren't calling any single bit from your code in the main function... You never instantiate P1, you never call the standalone function Print, so how could any of your logging statement ever get called?

"address not from malloc()" error using electric fence

I've been writing a test case program to demonstrate a problem with a larger program of mine,
and the test case has a bug that the original program does not.
Here's the header file:
// compiled with g++ -I/usr/local/bin/boost_1_43_0 -Wall -std=c++0x -g test.cpp
#include <bitset>
#include <boost/shared_ptr.hpp>
#include <vector>
typedef std::vector< std::vector< std::bitset<11> > > FlagsVector;
namespace yarl
{
namespace path
{
class Pathfinder;
}
namespace level
{
class LevelMap
{
// Member Variables
private:
int width, height;
FlagsVector flags;
public:
boost::shared_ptr<path::Pathfinder> pathfinder;
// Member Functions
LevelMap(const int, const int);
int getWidth() const {return width;}
int getHeight() const {return height;}
bool getFifthBit(const int x, const int y) const
{
return flags.at(x).at(y).test(5);
}
};
class Level
{
// Member Variables
public:
LevelMap map;
// Member Functions
public:
Level(const int w=50, const int h=50);
};
}
namespace path
{
class Pathfinder
{
// Member Variables
private:
boost::shared_ptr<level::LevelMap> clientMap;
// Member Functions
public:
Pathfinder() {}
Pathfinder(level::LevelMap* cm)
: clientMap(cm) {}
void test() const;
};
}
}
and here's the implementation file:
#include <iostream>
#include "test.hpp"
using namespace std;
namespace yarl
{
namespace level
{
LevelMap::LevelMap(const int w, const int h)
: width(w), height(h), flags(w, vector< bitset<11> >(h, bitset<11>())),
pathfinder(new path::Pathfinder(this))
{}
Level::Level(const int w, const int h)
: map(w,h)
{
map.pathfinder->test();
}
}
namespace path
{
void Pathfinder::test() const
{
int width = clientMap->getWidth();
int height = clientMap->getHeight();
cerr << endl;
cerr << "clientMap->width: " << width << endl;
cerr << "clientMap->height: " << height << endl;
cerr << endl;
for(int x=0; x<width; ++x)
{
for(int y=0; y<height; ++y)
{
cerr << clientMap->getFifthBit(x,y);
}
cerr << "***" << endl; // marker for the end of a line in the output
}
}
}
}
int main()
{
yarl::level::Level l;
l.map.pathfinder->test();
}
I link this program with electric fence, and when I run it it aborts with this error:
ElectricFence Aborting: free(bffff434): address not from malloc().
Program received signal SIGILL, Illegal instruction.
0x0012d422 in __kernel_vsyscall ()
backtracing from gdb shows that the illegal instruction is in the compiler-generated destructor of Pathfinder, which is having trouble destructing its shared_ptr. Anyone see why that is?
yarl::level::Level l;
You instantiate an automatic Level variable, which, in its constructor constructs its member pathfinder like so:
pathfinder(new path::Pathfinder(this))
Then in the Pathfinder constructor, it takes the Level pointer that you pass in and assigns that to a shared_ptr. The shared_ptr then takes ownership of this pointer.
This is incorrect for several reasons:
A shared_ptr should be used to manage dynamically allocated objects, not automatically allocated objects
If you want to use shared_ptr, then you should use it everywhere: as it is now, you pass raw pointers (e.g. to the constructor of Pathfinder, but then store them as shared_ptrs. This just opens a big can of ownership worms.
The correct way to assign this to a shared_ptr is to derive from enable_shared_from_this; note however that you cannot get a shared_ptr from this in a constructor.
When the shared_ptr is destroyed, it will try to delete the pointer it manages. In this case, however, that pointer is not to a dynamically allocated object (i.e., allocated with new), but to an automatically allocated object (i.e., on the stack). Hence, the error.
If you don't need something to take ownership of a resource, there is nothing wrong with using a raw pointer (or a reference, if you have that option).
You are constructing shared_ptr from a pointer which is not supposed to be managed by shared_ptr. (The this pointer)
When the last shared_ptr's copy is destroyed this memory is free'd - when in fact it should not - the this is on stack in this case.
There is a reason the constructor of shared_ptr is explicit - it is exactly to avoid such an unnoticed conversion from regular pointer, which is not to be managed by shared_ptr, to a shared_ptr - once you pass such a pointer into shared_ptr, your program is doomed - the only way out is by deleting the pointer you have not intended to delete.
In general it is advisable to construct shared pointer with new directly - such as ptr(new Somethings(x,y,z) - this way you don't risk an exception leaking your allocated, but unassigned to a shared_ptr memory.
The Level contains a LevelMap member variable. When the Level gets destroyed, it will also destroy its LevelMap.
On the other hand a pointer to this LevelMap member is passed to Pathfinder, which creates a shared_ptr<> from the passed pointer. This newly created shared_ptr<> thinks that it owns the object it points to and will try to destroy it once the Pathfinder gets destroyed.
So the LevelMap is destroyed several times.
In the example the LevelMap is created on the stack. Therefore the delete called by shared_ptr<> can see that the address is not from the heap and you get an error. If your real program also has this problem, but all those objects are dynamically allocated, the error will probably not be detected. You will just get silent memory corruption and weird crashes later on.