我在使用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)如何修复它。
答案 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
的先前值。
如果可以解除分配另一个分配的内存,则两个分配器“相等”,这在这里显然不是这样。