std::allocator<T>: 是否允许在 C++ 中构建未分配的内存?

std::allocator<T>: Is constructing on unallocated memory in C++ allowed?

所以我对C++比较陌生,最近遇到了std::allocatorclass。我知道这是用于创建 vectors、lists、deques 等的强大工具,我正在尝试了解更多相关信息。 让我感到困惑的一件事如下:

例如,如果我们定义一些 allocator<int> 表示为 alloc,我们使用它通过 auto const b = a.allocate(n) 在内存中分配 n 个位置,其中 b 是指向分配内存中第一个 int 元素的指针,那么,为了实际访问它,也有义务构造分配内存,对吧? 如果我们引入一些迭代指针 auto e=b,那么可以通过 alloc.construct(e++,int_obj) 执行构造,其中 int_obj 是类型 int 的某个用户初始化对象。只要对 construct 的调用总量小于 n,这一切都很好而且很温和。但是,我不太确定当用户调用 construct 的次数超过 n 时会发生什么。我最初预计会出现一些警告或错误消息,但什么也没有发生。作为一个简单的例子,这里是我尝试 运行:

的代码片段
int n{ 0 };                            // Size of the array is initialized to 0.
cin >> n;                              // User reads in the size.
allocator<int> alloc;                  // 'alloc' is an object that can allocate ints.
auto const b = alloc.allocate(n);      // Pointer to the beginning of the array. 
auto e = b;                            // Moving iterator that will point to the end of the array

for (int i = 0;i != 10;++i)
    alloc.construct(e++, i);           // We start constructing 10 elements in the array, regardless of the size n, which can in principle be less than 10.
for (auto i = b;i != e;++i)
    cout << *i << "\t";

最初我 运行 此代码用于 n=1,并且一切正常;它打印出从 0 到 9 的数字,即使我只为一个数字分配了 space。那已经是危险信号了,对吧?然后我将 n 更改为 2,程序在打印数字四后中断,这更符合我的预期。

我从这种行为中得出的结论是,尝试通过 std::allocator 构建尚未分配的内存是未定义和不可预测的,因此应该避免(一开始就很明显)。但是,这似乎是一个极其危险的陷阱,我想知道 C++ 中是否有一些内置的解决方法,在尝试构造未分配的内存时总是会阻止用户。

But, this seems as as extremely dangerous pitfall,

这当然是,您有责任避免这种陷阱。这就是为什么始终建议首先使用现有容器的原因,因为它们已经过仔细编写、审查和测试以避免此类错误。

如果您确实需要直接处理原始内存,通常最好编写您自己的容器,您可以按照类似的标准对其进行测试,而不是将手动内存管理与其余的程序逻辑交织在一起。

and I wanted to know if there is some build-in workaround in C++ that will always prevent user when trying to construct unallocated memory

不,因为这必然会导致 运行 编写时不正确的内容的时间成本。我不希望我的程序 运行 变慢,因为其他人 他们的 工作做得不好。

但是,有很多工具可以帮助您测试和诊断这些错误,例如:

  • clang 和 gcc 编译器有地址清理器,可以将这些检查编译到您的程序中(这是一个可选的编译器工具,而不是语言的一部分)
  • valgrind 是一个外部程序,其默认工具 (memcheck) 运行 是查找这些错误的真实程序。它很慢,但它用于测试或调试而不是用于实时程序