Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

taking over memory from std::vector

I use an external library which operates on large quantities of data. The data is passed in by a raw pointer, plus the length. The library does not claim ownership of the pointer, but invokes a provided callback function (with the same two arguments) when it is done with the data.

The data gets prepared conveniently by using std::vector<T>, and I'd rather not give up this convenience. Copying the data is completely out of the question. Thus, I need a way to "take over" the memory buffer owned by an std::vector<T>, and (later on) deallocate it in the callback.

My current solution looks as follows:

std::vector<T> input = prepare_input();
T * data = input.data();
size_t size = input.size();
// move the vector to "raw" storage, to prevent deallocation
alignas(std::vector<T>) char temp[sizeof(std::vector<T>)];
new (temp) std::vector<T>(std::move(input));
// invoke the library
lib::startProcesing(data, size);

and, in the callback function:

void callback(T * data, size_t size) {
    std::allocator<T>().deallocate(data, size);
}

This solution works, because the standard allocator's deallocate function ignores its second argument (the element count) and simply calls ::operator delete(data). If it did not, bad things could happen, as the size of the input vector might be quite a bit smaller than its capacity.

My question is: is there a reliable (wrt. the C++ standard) way of taking over the buffer of std::vector and releasing it "manually" at some later time?

like image 859
Grzegorz Herman Avatar asked Nov 26 '14 23:11

Grzegorz Herman


People also ask

How does C++ vector allocate memory?

Vectors are assigned memory in blocks of contiguous locations. When the memory allocated for the vector falls short of storing new elements, a new memory block is allocated to vector and all elements are copied from the old location to the new location. This reallocation of elements helps vectors to grow when required.

Does vector use more memory?

These abilities come at a price: vectors consume more memory in exchange to handle storage and grow dynamically in size.

Does std::vector clear free memory?

No, memory are not freed. In C++11, you can use the shrink_to_fit method for force the vector to free memory. Show activity on this post.


1 Answers

You can't take ownership of the memory from a vector, but you can solve your underlying problem another way.

Here's how I'd approach it - its a bit hacky because of the static global variable and not thread safe, but it can be made so with some simple locking around accesses to the registry object.

static std::map<T*, std::vector<T>*> registry;
void my_startProcessing(std::vector<T> * data) {
  registry.put(data->data(), data);
  lib::startProcesing(data->data(), data->size());
}

void my_callback(T * data, size_t length) {
  std::vector<T> * original = registry.get(data);
  delete original;
  registry.remove(data);
}

Now you can just do

std::vector<T> * input = ...
my_startProcessing(input);

But watch out! Bad things will happen if you add/remove elements to the input after you've called my_startProcessing - the buffer the library has may be invalidated. (You may be allowed to change values in the vector, as I believe that will write through the to data correctly, but that will depend on what the library allows too.)

Also this doesn't work if T=bool since std::vector<bool>::data() doesn't work.

like image 185
Michael Anderson Avatar answered Oct 31 '22 07:10

Michael Anderson