Round up allocation size to avoid misalignment (issue #226)

Before this change, requesting a large initial allocation could cause the
backing store to grow to an unaligned size. Since memory inside vector_downward
is relative to the end of the buffer, this then caused all memory in the buffer
to be misaligned and also misaligns any further loads and stores. Misaligned
loads and stores are undefined behavior and don't work in environments such as
emscripten (a JavaScript to C++ compiler).
This commit is contained in:
Evan Wallace 2015-07-02 14:05:45 -07:00
parent 185b9f9792
commit 47aab78233
1 changed files with 3 additions and 0 deletions

View File

@ -416,7 +416,10 @@ class vector_downward {
uint8_t *make_space(size_t len) { uint8_t *make_space(size_t len) {
if (len > static_cast<size_t>(cur_ - buf_)) { if (len > static_cast<size_t>(cur_ - buf_)) {
auto old_size = size(); auto old_size = size();
auto largest_align = AlignOf<largest_scalar_t>();
reserved_ += std::max(len, growth_policy(reserved_)); reserved_ += std::max(len, growth_policy(reserved_));
// Round up to avoid undefined behavior from unaligned loads and stores.
reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
auto new_buf = allocator_.allocate(reserved_); auto new_buf = allocator_.allocate(reserved_);
auto new_cur = new_buf + reserved_ - old_size; auto new_cur = new_buf + reserved_ - old_size;
memcpy(new_cur, cur_, old_size); memcpy(new_cur, cur_, old_size);