堆栈分配器与嵌入式竞技场的问题

时间:2014-08-07 23:38:59

标签: c++ c++11 move-semantics allocator

我在使用Howard Hinnant的stack-based allocator时遇到了崩溃,两者都在 带有Clang 3.4的64位Linux上的MacOS。这是一个最小的例子 在容器的析构函数中触发崩溃:

#include <vector>
#include "stack_alloc.h"

template <template <typename...> class C, typename T, size_t N>
using stack_container = C<T, stack_alloc<T, N>>;

using stack_vector = stack_container<std::vector, size_t, 4>;

int main()
{
  auto s = stack_vector{1, 2, 3};
  auto m = std::move(s);
}

编译如下:

clang++ -std=c++11 -stdlib=libc++ -g -Wall crash.cc && ./a.out

你有什么想法会发生这种崩溃吗?我也试过了 在竞技场实施方面重新实现stack_alloc short_alloc,但移动基于堆栈的容器时仍然会崩溃。

这是一个Linux回溯:

#0  _int_free (av=0x394f5b8760 <main_arena>, p=0x7fffffffe0f0, have_lock=0) at malloc.c:3901
#1  0x00000000004013eb in stack_alloc<unsigned long, 4ul>::deallocate (this=0x7fffffffe080, p=0x7fffffffe100, n=3)
    at ./stack_alloc.h:71
#2  0x0000000000401343 in capacity (this=0x7fffffffe060, this=0x7fffffffe060, __a=..., __p=0x7fffffffe100, __n=3)
    at .../include/c++/v1/memory:1443
#3  std::__1::__vector_base<unsigned long, stack_alloc<unsigned long, 4> >::~__vector_base (this=0x7fffffffe060)
    at .../include/c++/v1/vector:476
#4  0x0000000000400fa5 in std::__1::vector<unsigned long, stack_alloc<unsigned long, 4> >::~vector (this=0x7fffffffe060)
    at .../include/c++/v1/vector:481
#5  0x0000000000400f6e in main () at crash.cc:13

我感兴趣(i)如果有人可以重现错误,(ii)如何修复它。

2 个答案:

答案 0 :(得分:3)

您使用的是不符合要求的C ++ 11 stack_alloc。作为Hinnant himself wrote

  

我用一个完全是C ++ 11的新分配器更新了这篇文章   符合。它取代的分配器不完全是C ++ 03,也不是C ++ 11   符合,因为副本不相等。

更正后的版本名为short_alloc,且为found here

用法需要将堆栈缓冲区放在分配器之外(使用Hinnant's notation):

int main()
{
  arena<N> a; // change N to required space
  auto s = SmallVector({1, 2, 3}, Alloc{a});
  auto m = std::move(s);
}

答案 1 :(得分:2)

当你移动构造第二个容器时,容器移动构造分配器并接管指针。当第二个容器死亡时,它会尝试释放指针并错误地执行,从而在deallocate()中的指针比较中导致UB。

“allocator”不满足分配器要求,特别是:

  

X a1(move(a))发布:a1等于a的先前值。

如果可以解除分配另一个分配的内存,则两个分配器“相等”,这在这里显然不是这样。

相关问题