Я написал собственный LinearAllocator, который я использую с вектором.Распределитель может взять другой Распределитель в качестве параметра шаблона / конструктора, чтобы выделить его исходное хранилище.Прямо сейчас он делает первоначальное распределение с помощью std :: allocator, но когда я переполняю вектор, это не выдает ошибку.Я понимаю, что это неопределенное поведение, поэтому я не могу гарантировать segfault, но оно последовательно позволяет мне изменять 1037600 элементов с начала вектора (размером 64).
Я распечатал и изменил каждый элемент доэто дало мне ошибку:
template <class T, size_t N, class Alloc = std::allocator<uint8_t>>
class LinearAllocator
{
public:
typedef T value_type;
LinearAllocator()
:m_memory{m_alloc.allocate(N)}, m_head{m_memory}
{
}
template<class U>
LinearAllocator(LinearAllocator<U, N> const& other) noexcept
:m_memory{other.m_memory}, m_head{other.m_head}
{}
template<class U>
bool operator==(LinearAllocator<U, N> const& other) const noexcept
{
return m_memory == other.m_memory && m_head == other.m_head;
}
template<class U>
bool operator!=(LinearAllocator<U, N> const& other) const noexcept
{
return !(*this == other);
}
T* allocate(const size_t n)
{
uint8_t* memory = static_cast<uint8_t*>(m_memory);
uint8_t* head = static_cast<uint8_t*>(m_head);
if(n == 0)
{
return nullptr;
}
if(n > static_cast<size_t>(-1) / sizeof(T))
{
throw std::bad_array_new_length();
}
if(n > N) { throw std::bad_alloc(); }
if(memory + N < head + n) { head = memory; }
void* pv = m_head;
head += n;
m_head = static_cast<void*>(head);
return static_cast<T*>(pv);
}
void deallocate(T* const p, size_t) const noexcept
{}
private:
Alloc m_alloc = Alloc();
void* m_memory = nullptr;
void* m_head = nullptr;
};
int main()
{
std::vector<uint8_t, LinearAllocator<uint8_t, 64>> vec(64, 1);
//std::vector<uint8_t> vec(65, 1);
std::cout << (void*)vec.data() << std::endl;
for(size_t i = 0; i < vec.size()+10000000; ++i)
{
std::cout << i << " " << (int)vec[i]++ << " " << (int)vec[i]<< "\n";
}
}
Я ожидал, что это потерпит неудачу при переполнении в элементе 64, так как я думал, что это память, выделенная для кучи.Но, похоже, он потерпел неудачу в той же точке, элемент 1037663, далеко позади, где я ожидал.В частности:
$ ./run
0 1 2
1 1 2
...
1037662 0 1
1037663 0 1
Ошибка сегментации: 11