Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 带有嵌入式arena的堆栈分配器出现问题_C++_C++11_Move Semantics_Allocator - Fatal编程技术网

C++ 带有嵌入式arena的堆栈分配器出现问题

C++ 带有嵌入式arena的堆栈分配器出现问题,c++,c++11,move-semantics,allocator,C++,C++11,Move Semantics,Allocator,我在使用Howard Hinnant's时遇到崩溃,两个都是在 MacOS和64位Linux上的Clang 3.4。这里有一个最小的例子 触发容器析构函数中的崩溃: #include <vector> #include "stack_alloc.h" template <template <typename...> class C, typename T, size_t N> using stack_container = C<T, stack_all

我在使用Howard Hinnant's时遇到崩溃,两个都是在 MacOS和64位Linux上的Clang 3.4。这里有一个最小的例子 触发容器析构函数中的崩溃:

#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);
}
你知道这次坠机的原因吗?我也试过了 从竞技场实施方面重新实施了
stack\u 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
在malloc.c:3901 #堆栈中的1 0x00000000004013eb_alloc::解除分配(this=0x7fffffffe080,p=0x7fffffffe100,n=3) at./stack_alloc.h:71 #容量为2 0x0000000000401343(此=0x7fffffffe060,此=0x7FFFFFE060,此=0x7fffffffe060,此=0x7fffffffe060,此=0x7FFFFFFFFFE100,此=0x7fffffffe060 at…/include/c++/v1/内存:1443 #3标准::uuuu 1::uuuu向量基::~uu向量基(此=0x7fffffffe060) at…/include/c++/v1/vector:476 #std:uuu 1::vector::~vector中的4 0x0000000000400fa5(此=0x7fffffffe060) at…/include/c++/v1/vector:481 #5 0x0000000000400f6e在崩溃时的主()中。cc:13
我感兴趣的是(I)人们是否能够重现错误,以及(ii)如何修复错误。

当您移动构造第二个容器时,容器移动构造分配器并接管指针。当第二个容器死亡时,它尝试取消分配指针,但操作错误,导致在
deallocate()
中的指针比较中出现UB

“分配器”不满足分配器要求,尤其是:

xa1(移动(a))
Post:
a1
等于
a
的先前值


如果一个分配器可以释放另一个分配器分配的内存,那么两个分配器是“相等的”,这里显然不是这样。

您使用的是不一致的C++11
堆栈alloc
。作为希南特

我用一个完全是C++11的新分配器更新了本文 符合。它替换的分配器不是完全的C++03或C++11 一致的,因为副本不相等

更正后的版本名为
short\u alloc
,并且为

使用时需要将堆栈缓冲区放置在分配器外部(使用):

intmain()
{
竞技场a;//将N更改为所需空间
自动s=小向量({1,2,3},Alloc{a});
自动m=标准::移动;
}

另一种方式是分配器的状态永远不能是分配器的对象标识本身。有趣的是,这个错误归结为分配器相等的概念。但如果分配器包含自己的内存,那么根据定义,两个不同的实例永远不可能相等。这让我想知道什么是正确的解决方案?实现
在容器上传播\u移动\u分配
(和
*\u复制*
)以指示两个不同的容器应始终使用各自的分配器是否足够?确认。这是“竞技场分配器”的标准概念(例如,使用用户提供的竞技场)。我理解“旧的”
stack\u alloc
不符合标准,在这种情况下,移动操作会导致UB。虽然
short\u alloc
解决了这个问题,但我使用
stack\u alloc
的原因是界面:它是一个透明的替换,不需要任何用户代码更改。使用
short\u alloc
,我需要添加n竞技场簿记的ew代码,这是我试图避免的。是否有可能创建一个分配器,可以在上面绘制的
stack\u容器
style?界面中使用?@MatthiasVallentin否这正是Hinnant引用的要点:旧版本在调用站点更干净,但它不符合C++11标准因为拷贝是不平等的。写你自己的分配者提案使其合法化是没有办法的:-)但是我感觉到你的痛苦(我经常使用短配码,这会伤害我的眼睛,特别是因为为了性能,你还需要做一个
v.reserve(N/sizeof(T))
来占领整个竞技场)@TemplateRex:没错。你不可能有一个完全看不见的自动存储器。这就是说,我认为自动arena变量对于需要这种内存局部性的少数情况是完全合适的、可管理的和合理的。下一个最好的方法是“小尺寸优化”向量,具有可配置的内部存储量;与
basic_string
类似,但更大,并且前面有迭代器交换保证。很可能你不会同时想要两者。
#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
int main()
{
  arena<N> a; // change N to required space
  auto s = SmallVector({1, 2, 3}, Alloc{a});
  auto m = std::move(s);
}