Memory Management with shared_vectorΒΆ

page vectormem

The shared_vector class is a std::vector like class which implements sharing data by reference counting.

Internally memory is tracked with the shared_ptr reference counting smart pointer. This allows a custom destructor to be specified. This allows a vector to borrow memory allocated by 3rd party libraries which require special cleanup.

In place element modification is allowed. It is left to user code to ensure that such modification is safe, either from application specific knowledge, or by calling make_unique explicitly, or implicitly by calling resize prior to making modifications.

extern "C" {
  // array embedded in C structure
  struct composite {
    int other, stuff;
    char buf[42];
  }

  // Unknown relation between array and handle
  typedef void* handle_type;
  handle_type mylib_alloc(void);
  char *mylib_mem(handle_type);
  void mylib_free(handle_type);
}

// Note that mylibcleaner must be copy constructable
struct mylibcleaner {
  handle_type handle;
  mylibcleaner(handle_type h) :handle(h) {}
  void operator()(char*){ mylib_free(handle);}
};

struct compcleaner {
  void operator()(char* c){ free(c-offsetof(composite,buf)); }
};

void main() {

  unsigned char* buf=calloc(42,1);

  shared_vector<epicsUInt8> a(buf, &free);

  a.clear(); // calls free(ptr)


  composite *c=malloc(sizeof(*c));
  assert(c!=NULL);

  shared_vector<char> d(c->buf, compcleaner());

  d.clear(); // calls free(ptr-offsetof(composite,buf))


  void *handle=mylib_alloc();
  char *hmem=mylib_mem(handle);
  assert(hmem!=NULL);

  shared_vector<epicsUInt8> b(hmem, mylibcleaner(handle));

  b.clear(); // calls mylib_free(handleptr)
}