4

I am copying a process' memory in a vector<char> buffer and would like the memory allocated for this vector to have a higher alignment than just the default.

This is because I am looking for arbitrarily typed patterns in that buffer where memory could represent anything - I expect any value/type pair I am looking for to be aligned according to it's type.

Maybe I could resolve this using an 'offset' but I'd rather have my char buffer be aligned.

Is there any way to do this other than creating a vector<large_type> instead?

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
PinkTurtle
  • 6,942
  • 3
  • 25
  • 44
  • You can provide a custom allocator which allocates memory with the your alignment requirements. – Yashas Mar 17 '19 at 17:07
  • Will be looking forward to this. Thanks. – PinkTurtle Mar 17 '19 at 17:10
  • @Yashas Please don't make technical suggestions towards the answer in the comments section, bypassing the peer review system. That's what the answer section is for. If you don't have time to write a full answer right now, that's fine: someone else can do it! Cheers :) – Lightness Races in Orbit Mar 17 '19 at 17:14

2 Answers2

4

I could solve my issue with a custom allocator.

Example with boost::alignment::aligned_allocator

#include <vector>
#include <boost/align/aligned_allocator.hpp>

template <typename T>
using aligned_vector = std::vector<T, boost::alignment::aligned_allocator<T, 16>>;
// 16 bytes aligned allocation

See also How is a vector's data aligned?.

PinkTurtle
  • 6,942
  • 3
  • 25
  • 44
0

I had used something like the following for this purpose:


#include <iostream>
#include <vector>

template<typename T>
class AlignedVector {
 public:
  AlignedVector() : data_(nullptr) {}
  AlignedVector(int n)
      : char_vec_(sizeof(T)*(n+1)),
        data_(AlignedAddr(char_vec_.data())),
        size_(n) {}

  T* operator[](size_t n) { return data_[n]; }
  const T* operator[](size_t n) const { return data_[n]; }

  T* data() { return data_; }
  const T* data() const { return data_; }

  size_t size() const { return size_; }
  void resize(size_t n) {
    char_vec_.resize(sizeof(T)*(n+1));
    data_ = AlignedAddr(char_vec_.data());
    size_ = n;
  }

 private:
  static T* AlignedAddr(char* addr) {
    return (T*)(addr + sizeof(T) - ((size_t)addr % sizeof(T)));
  }

  std::vector<char> char_vec_;
  T* data_;
  size_t size_;
};

int main()
{
  AlignedVector<int[128]> vec(13);
  std::cout << (size_t)vec.data() << std::endl;
}

The main function that performs the alignment is static T* AlignedAddr(char* addr). Basically for an N-element type T array we allocate enough size for (N+1) elements and return the lowest aligned address inside the allocated area.

To enable other methods in std::vector<T> one would need to implement them using data_ and size_ individually. This worked for me since I usually only use few of them.

Edy
  • 462
  • 3
  • 9