One of my favorite aspects of unique_ptr is the automatic memory management it provides. I would like to use unique_ptr with something like a GSL vector.
However, gsl_vector has its own mechanism for freeing memory (gsl_vector_free). Is there a way to force the unique pointer to use GSL's vector freeing method? Valgrind (correctly) reports a mismatched use of malloc/delete when creating a unique_ptr<gsl_vector> below:
#include <memory>
#include <gsl/gsl_vector.h>
void mem_gsl() {
gsl_vector *vec;
vec = gsl_vector_calloc(2);
gsl_vector_set(vec, 0, 2.0);
printf("%f\n", gsl_vector_get(vec, 0));
gsl_vector_free(vec); // Without this, there is a memory leak.
}
void mem_unique_ptr() {
std::unique_ptr<gsl_vector> vec;
vec.reset(gsl_vector_calloc(2));
// Using .get() each time I want to use the gsl_vector seems like overhead.
gsl_vector_set(vec.get(), 0, 2.0);
printf("%f\n", gsl_vector_get(vec.get(), 0));
// Valgrind correctly reports a mismatched use of delete and free.
}
int main(int argc, char *argv[]) {
mem_gsl();
mem_unique_ptr();
return 0;
}
Additionally, having to call get() each time I want to access a vector element seems rather tedious. Is there a way around this?
You can do it by providing std::unique_ptr with a custom deleter. Something like this would probably do:
auto del = [](gsl_vector* p) { gsl_vector_free(p); };
std::unique_ptr<gsl_vector, decltype(del)> vec(gsl_vector_calloc(2), del);
Having a make_unique_gsl_vector amd a custom deleter:
#include <memory>
// Fake gsl
typedef int gsl_vector;
gsl_vector* gsl_vector_calloc(std::size_t) { return 0; }
void gsl_vector_free(gsl_vector*) {}
// Deleter
struct gsl_vector_deleter {
void operator () (gsl_vector* p) {
gsl_vector_free(p);
}
};
// Unique Pointer
typedef std::unique_ptr<gsl_vector, gsl_vector_deleter> unique_gsl_vector;
unique_gsl_vector make_unique_gsl_vector() {
return unique_gsl_vector(gsl_vector_calloc(2));
}
int main() {
make_unique_gsl_vector();
return 0;
}
To avoid the .get() calls and other boilerplate associated with wrapping a gsl_vector in a unique_ptr, you could create a small RAII wrapper.
namespace gsl {
class vector
{
std::unique_ptr<gsl_vector, decltype(&gsl_vector_free)> v_;
public:
explicit vector(std::size_t num)
: v_(gsl_vector_calloc(num), gsl_vector_free)
{}
double operator[](std::size_t idx) const
{
return gsl_vector_get(v_.get(), idx);
}
void set(std::size_t idx, double value)
{
gsl_vector_set(v_.get(), idx, value);
}
};
}
This not only avoids boilerplate, but also allows you to easily extend functionality, say for instance, adding a constructor that takes a std::initializer_list<double> so you can construct and initialize the vector in a single expression.
Live example
Related
I often encounter a situation when I have complex class (e.g. implementing some numerical algorithm like Partial Differential Equation Solver) with data arrays which it can either own or bind from external context depending on use case. The problem is how to make robust destructor for such class. Simple way is to make boolean flag which indicates wheather the array is owned. E.g.
// simplest example I can think about
class Solver{
int nParticles;
bool own_position;
bool own_velocity;
double* position;
double* velocity;
// there is more buffers like this, not just position and velocity, but e.g. mass, force, pressure etc. each of which can be either owned or binded externally independently of each other, therefore if there is 6 buffers, there is 2^6 variants of owership (e.g. of construction/destruction)
void move(double dt){ for(int i=0; i<n; i++){ position[i]+=velocity[i]*dt; } }
~Solver(){
if(own_position) delete [] position;
if(own_velocity) delete [] velocity;
}
};
Naturally, this motivates to make a template wrapper around the array pointer (should I call it smart pointer ?):
template<typename T>
struct Data{
bool own;
T* data;
~Data{ if(own)delete [] T; }
};
class Solver{
int nParticles;
Data<double> position;
Data<double> velocity;
void move(double dt){ for(int i=0; i<n; i++){ position.data[i]+=velocity.data[i]*dt; } }
// default destructor is just fine (?)
};
Question:
This must be common pattern, do I reinvent a wheel here?
Is something like this in C++ standard library ? (sorry, I'm rather a physicist than a programmer)
are there some catches to think about ?
----------------------------------------
EDIT: To make clear what bind to external contex mean (as Albjenow suggested):
case 1) private/internal work array (no shared ownership)
// constructor to allocate own data
Data::Data(int n){
data = new double[n];
own = true;
}
Solver::Solver(int n_){
n=n_;
position(n); // type Data<double>
velocity(n);
}
void flowFieldFunction(int n, double* position, double* velocity ){
for(int i=0;i<n;i++){
velocity[i] = sin( position[i] );
}
}
int main(){
Solver solver(100000); // Solver allocates all arrays internally
// --- run simulation
// int niters=10;
for(int i=0;i<niters;i++){
flowFieldFunction(solver.n,solver.data.position,solver.data.velocity);
solver.move(dt);
}
}
case 2) Bind To External data array (e.g. from other class)
Data::bind(double* data_){
data=data_;
own=false;
}
// example of "other class" which owns data; we have no control of it
class FlowField{
int n;
double* position;
void getVelocity(double* velocity){
for(int i=0;i<n;i++){
velocity[i] = sin( position[i] );
}
}
FlowField(int n_){n=n_;position=new double[n];}
~FlowField(){delete [] position;}
}
int main(){
FlowField field(100000);
Solver solver; // default constructor, no allocation
// allocate some
solver.n=field.n;
solver.velocity(solver.n);
// bind others
solver.position.bind( field.position );
// --- run simulation
// int niters=10;
for(int i=0;i<niters;i++){
field.getVelocity(solver.velocity);
solver.move(dt);
}
}
Here is a simple way to do what you want without having to write any smart pointer yourself (it would be hard to get the fine details correct) or writing a custom destructor (which would mean more code and bug potential from the other special member functions required by the rule of five):
#include <memory>
template<typename T>
class DataHolder
{
public:
DataHolder(T* externallyOwned)
: _ownedData(nullptr)
, _data(externallyOwned)
{
}
DataHolder(std::size_t allocSize)
: _ownedData(new T[allocSize])
, _data(_ownedData.get())
{
}
T* get() // could add a const overload
{
return _data;
}
private:
// Order of these two is important for the second constructor!
std::unique_ptr<T[]> _ownedData;
T* _data;
};
https://godbolt.org/z/T4cgyy
The unique_ptr member holds the self-allocated data, or is empty when externally owned data is used. The raw pointer points to the unique_ptr contents in the former case, or the external content in the latter case. You could modify the constructors (or only make them accessible via static member functions like DataHolder::fromExternal() and DataHolder::allocateSelf() which return DataHolder instances created with the appropriate constructor) to make accidental misuse harder.
(Note that the members are initialized in the order they are declared in the class, not in the order of the member initializer lists, so having the unique_ptr before the raw pointer is important!)
And of course, this class cannot be copied (due to the unique_ptr member) but can be move-constructed or -assigned (with the correct semantics). Works out of the box as it should.
One solution is to separate data ownership from your solver algorithm. Having the algorithm optionally manage lifetime of its inputs isn't good design because it leads to entanglement of separate concerns. The solver algorithm should always refer to already existing data. And have another extra class that owns data, if necessary, and have lifetime no shorter than that of the algorithm, e.g.:
struct Solver {
int nParticles;
double* position;
double* velocity;
};
struct Data {
std::vector<double> position, velocity; // Alternatively, std::unique_ptr<double[]>.
template<class T>
static T* get(int size, std::vector<T>& own_data, T* external_data) {
if(external_data)
return external_data;
own_data.resize(size);
return own_data.data();
}
double* get_position(int nParticles, double* external_position) { return get(nParticles, position, external_position); }
double* get_velocity(int nParticles, double* external_velocity) { return get(nParticles, velocity, external_velocity); }
};
struct SolverAndData {
Data data;
Solver solver;
SolverAndData(int nParticles, double* external_position, double* external_velocity)
: solver{
nParticles,
data.get_position(nParticles, external_position),
data.get_velocity(nParticles, external_velocity)
}
{}
SolverAndData(SolverAndData const&) = delete;
SolverAndData& operator=(SolverAndData const&) = delete;
};
int main() {
SolverAndData a(1, nullptr, nullptr);
double position = 0;
SolverAndData b(1, &position, nullptr);
double velocity = 0;
SolverAndData c(1, nullptr, &velocity);
SolverAndData d(1, &position, &velocity);
}
Can I force std::vector to not deallocate its memory after the vector goes out of scope?
For example, if I have
int* foo() {
std::vector<int> v(10,1); // trivial vector
return &v[0];
}
int main()
{
int* bar = foo();
std::cout << bar[5] << std::endl;
}
There is no guarantee that the values will still be accessible here.
I am currently simply doing this
int* foo() {
std::vector<int> v(10,1);
int* w = new int[10];
for (int i=0; i<10; i++) {
w[i] = v[i];
}
return w;
}
but it is a little wasteful to repopulate a whole new array. Is there a way to force std::vector to not delete its array?
Note: I am not returning the vector itself because I am interfacing c++ with python using SWIG, and ARG_OUTVIEW_ARRAY requires a raw pointer and, in fact, an intentional memory leak. I would still however like to be able to make use of vector features while constructing the data itself.
It is possible but you should never do it. Forcing a vector to leave memory leak is a terrible idea and if you need such a thing then you need to re-think your design. std::vector is a resource managing type whose one of the main goals is to ensure that we don't have a leak. Never try to break that.
Now, to answer your specific question: std::vector takes an allocator type as second template parameter which is default to std::allocator<T>. Now you can write a custom allocator that doesn't release any memory and use that with your vector. Writing a custom allocator is not very trivial work, so I'm not going to describe that here (but you can Google to find the tutorials).
If you really want to use custom allocator then you must ensure that your vector never triggers a grow operation. Cause during growing capacity the vector will move/copy data to new location and release the old memories using the allocator. If you use an allocator that leaks then during growing you not only retain the final data, but also retain the old memories which I'm sure that you don't want to retain. So make sure that you create the vector with full capacity.
The vector is desiged to prevent leaks.
But if you want to shoot yourself in the foot, it's possible. Here's how you prevent the vector from deallocating its internal array:
int *foo()
{
std::vector<int> v(10,1);
int *ret = v.data();
new (&v) std::vector<int>; // Replace `v` with an empty vector. Old storage is leaked.
return ret;
}
As the other answers say, you should never do it.
No.
Vectors are not implemented to have memory leaks, and the interface does not provide a way to create one.
You can't "steal" the memory (removing ownership of it from the vector), which is possibly a bit of a shame.
Sorry, but you are going to have to either copy (as you're doing now), or not use vector.
This is a bad idea, but possible by creating a custom allocator that does not deallocate as said in other answers.
For example : (boilerplate mostly from cppref)
#include <cstdlib>
#include <new>
#include <vector>
template <typename T>
struct LeakingAllocator
{
using value_type = T;
LeakingAllocator() = default;
template <typename U> constexpr LeakingAllocator(const LeakingAllocator<U>&) noexcept {}
T* allocate(std::size_t n)
{
if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc(); // check for overflow
if(auto p = static_cast<T*>(std::malloc(n*sizeof(T)))) return p; // return p if malloc returns a valid object
throw std::bad_alloc(); // otherwise just throw.
}
void deallocate(T* p, std::size_t) noexcept { /*leak intentionally*/ }
};
template <typename T, typename U>
bool operator==(const LeakingAllocator<T>&, const LeakingAllocator<U>&) { return true; }
template <typename T, typename U>
bool operator!=(const LeakingAllocator<T>&, const LeakingAllocator<U>&) { return false; }
template <typename T>
using LeakingVector = std::vector<T, LeakingAllocator<T>>;
Then code like
int* ret()
{
LeakingVector<int> a;
a.resize(10);
return &a[0];
}
int main()
{
auto ptr = ret();
*ptr = 10;
std::cout << *ptr;
}
becomes valid.
Not sure but, yes.
You can create a custum allocator who do nothing when deallocate => leak
Or may be you can jsut create your vectoron the heap so it will leak anyway.
int* foo() {
std::vector<int>* v = new std::vector<int>(10,1);
return &((*v)[0]);
// no delete
}
int main()
{
int* bar = foo();
std::cout << bar[5] << std::endl;
}
No.
And you're doing it wrong. Return the vector instead so the lifetime works out:
Write your own special Python memory vector class, something like (most crudely):
template <typename T>
class python_vector
{
T* buffer_;
public:
python_vector(size_t n, const T& value) : buffer_{new T(n)}
{}
// copy, assignment, operator[](), *etc*
~python_vector()
{
// DO NOTHING!
}
}
python_vector<int> foo() {
python_vector<int> v(10,1);
// process v
return v;
}
int main()
{
python_vector<int> bar = foo(); // copy allusion will build only one python_vector here
std::cout << bar[5] << std::endl;
}
In C++ you would most probably write:
auto foo()
{
std::vector<int> v(10,1); // trivial vector
return v;
}
int main()
{
const auto bar = foo();
std::cout << bar[5] << std::endl;
}
I am trying to implement my own version of vector in c++.
So far I have done this..
#include<iostream>
#include<string>
using namespace std;
template<class T>
class vec
{
public:
T *a;
int i,N;
vec(int N=0):N(N)
{
i=-1;
a=(T *)malloc(N*sizeof(T));
}
void push_back(const T& t);
T at(const int& index) const;
};
template<class T>
void vec<T>::push_back(const T& t)
{
if(++i==N)
{
a=(T *)realloc(a,(++N)*sizeof(T));
}
a[i]=t;
}
template<class T>
T vec<T>::at(const int& index) const
{
return a[index];
}
int main()
{
vec<string> v;
v.push_back("2");
v.push_back("1");
v.push_back("3");
cout<<v.at(0)<<endl;
return 0;
}
But I am getting a run time error when I run this
Where is the error in the above code?
I am using c++ and visual studio to run.
In this case you need to use placement new.
something like this:
// Allocate memory
void* mem = malloc(sizeof(std::string));
// Call constructor via placement new on already allocated memory
std::string* ptr = new (mem) std::string();
But then, you are forced to explicitly call destructor for this memory
ptr->~std::string();
Overall - this is not really good way to achieve what you want. It's more convenient to use usual new\delete operators and copy internal data on re-allocation (how it was done in STL vector)
In general, templates arguments can be abstract classes, as the program below also shows. But it seems that the compare functor in sort must not be abstract. At least the following does not compile with VC++ 11 and on Oracle Studio 12.
#include <vector>
#include <algorithm>
class Functor
{
public:
virtual bool operator()(int a, int b) const = 0;
};
class MyFunctor: public Functor
{
public:
virtual bool operator()(int a, int b) const { return true; }
};
int _tmain(int argc, _TCHAR* argv[])
{
vector<Functor> fv; // template of abstract class is possible
vector<int> v;
MyFunctor* mf = new MyFunctor();
sort(v.begin(), v.end(), *mf);
Functor* f = new MyFunctor();
// following line does not compile:
// "Cannot have a parameter of the abstract class Functor"
sort(v.begin(), v.end(), *f);
return 0;
}
Now, I wonder whether this is a general property of functor arguments, or does it depend on the STL implementation? Is there a way to get, what I wanted to do?
Functors generally need to be copyable. Polymorphic base classes are generally not copyable, and abstract bases never.
Update: Thanks to the comments by #ahenderson and #ltjax, here's a very simple way to produce a wrapper object that holds your original, polymorphic reference:
#include <functional>
std::sort(v.begin(), v.end(), std::ref(*f));
// ^^^^^^^^^^^^
The result of std::ref is a std::refrence_wrapper which is exactly what you need: A class with value semantics that holds a reference to your original object.
The fact that functors get copied throws off lots of people who want to accumulate something inside the functor and then wonder why the results are off. The functor should really take a reference to an external object. To wit:
Bad! Won't work as you expect; the functor may get copied arbitrarily:
struct Func1 {
int i;
Func1() : i(0) { }
void operator()(T const & x) { /* ... */ }
};
Func1 f;
MyAlgo(myContainer, f);
Good: You provide the accumulator; it's safe to copy the functor:
struct Func2 {
int & i;
Func2(int & n) : i(n) { }
void operator()(T const & x) { /* ... */ }
};
int result;
MyAlgo(myContainer, Func2(result));
As Kerrek has said you can't do it directly:
But one level of indirection and you're OK.
struct AbstractFunctor
{
AbstractFunctor( Functor * in_f ): f(in_f) {}
// TODO: Copy constructor etc.
Functor * f;
bool operator()(int a, int b) const { return (*f)(a,b); }
};
int main()
{
vector<int> v;
Functor * mf = new MyFunctor();
sort(v.begin(), v.end(), AbstractFunctor(mf) );
}
As Kerrek and Michael Anderson said, you can't do it directly. As Michael shows, you can write a wrapper class. But there's also one in std:: :
sort(v.begin(),
v.end(),
std::bind(&Functor::operator(),
mf,
std::placeholders::_1,
std::placeholders::_2) );
How do I define a typedef for a fixed length array so that I can also 'new'. The following does not work:
typedef double Vector[3];
Vector *v = new Vector; // does not compile
We are trying to wrap into C++ some old C code which handles float * and float (*)[3] in a generic way.
The pointer to an double[3] is double * - so this will work:
typedef double Vector[3];
double *v = new Vector;
But I suggest you don't use it that way - to delete the array you need the array-delete-operator:
delete[] v;
But on new Vector you don't see it is an array and so it might be forgotten.
This case is handled (and strongly recommended to avoid) in Scott Meyers Effective C++. So better don't use an typedef here.
class Vector
{
public: // methods
double * data() { return mData; }
const double * data() const { return mData; }
double & operator[](int i) { return mData[i]; }
double operator[](int i) const { return mData[i]; }
private: // attributes
double mData[3];
};
will allow
Vector * pv = new Vector;
Vector & v = *pv;
v[0] = 1;
v[1] = 2;
v[2] = 3;
pass_it_to_legacy_lib(v.data());
delete pv;
One issue with your original example is that it would invoke the new operator where the new[] would actually be correct. Also, it would make it non-obvious that delete[] had to be used instead of plain delete.
The class approach doesn't need new[] and takes full advantage of the apriori fixed length.
If you're happy to use templates in your C++ code, something like this could work..
template <typename T, int S>
struct array
{
array() : _inst() {}
template<typename _F>
void operator()(_F & f)
{
f(_inst);
}
operator T*() { return _inst; }
// real array
T _inst[S];
};
typedef array<double, 4> d4;
void foo(double*)
{
}
int main(void)
{
d4 d; // no need for new, but you can use if you want
// first way to call is to pass the function to the array object, which will then
// visit
d(foo);
// take advantage of the type operator (operator T*)
foo(d);
}
#include <cassert>
#include <vector>
using namespace std;
template<typename Type, int Dimension>
const vector<Type> make_fixed_vector(const Type& value = Type())
{
return vector<Type>(Dimension, value);
}
int main(void)
{
vector<int> v3 = make_fixed_vector<int, 3>();
assert(v3.size() == 3);
}
C++1x compilers are able to deduce the type of a variable, which is handy when declaring multi-dimensional "fixed" vectors using this technique:
.
.
.
template<typename Type, int Rows, int Columns>
const vector<vector<Type> > make_fixed_vector_vector(const Type& value = Type())
{
return vector<vector<Type> >(Rows, make_fixed_vector<Type, Columns>(value));
}
int main(void)
{
auto vv = make_fixed_vector_vector<int, 3, 4>(42);
assert(vv.size() == 3);
assert(vv[0].size() == 4);
assert(vv[0][0] == 42);
assert(vv[2][3] == 42);
}
I had this simple idea when programming a parser-function for list expressions which shall return a fixed-size vector of vector of integers. For example, a vector<vector<int> >(1) for a expression like "(0,8)", but a vector<vector<int> >(2) for a expression like "(3-4)(5)" and so on. In the application up to 5 parenthesized definitions are possible, which represent logical references to program data. I first try to parse a vector<vector<int> >(5). Worked? Ok, got reference type A, the most detailed one. Otherwise vector<vector<int> >(4) indicates a reference type B etc.
For this purpose make_fixed_vector worked well, but from a general perspective the technique has flaws. Most notably, since make_fixed_vector returns no true type, its dimension(s) cannot be checked at compile-time. At runtime reserve, resize and push_back calls are possible. And, since function templates cannot have default template arguments, custom allocators require more typing:
template<typename Type, int Dimension, template<typename> class Allocator>
const vector<Type Allocator<Type> > make_fixed_vector(const Type& value = Type())
{
return vector<Type, Allocator<Type> >(Dimension, value);
}
vector<int> v3 = make_fixed_vector<int, 3, std::allocator>();
etc. etc. But this technique keeps smaller projects basic. Unless this virtue is relevant Boost's boost::array might be more realistic.