c++ - 新数组放置需要缓冲区中未指定的开销?

标签 c++ memory-management standards placement-new

C++11 2月草案的

5.3.4 [expr.new]给出了例子:

new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f).

Here, x and y are non-negative unspecified values representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by operator new[]. This overhead may be applied in all array new-expressions, including those referencing the library function operator new[](std::size_t, void*) and other placement allocation functions. The amount of overhead may vary from one invocation of new to another. —end example ]

现在看下面的示例代码:

void* buffer = malloc(sizeof(std::string) * 10);
std::string* p = ::new (buffer) std::string[10];

根据上面的引用,第二行 new (buffer) std::string[10] 会在内部调用 operator new[](sizeof(std::string) * 10 + y, buffer)(在构造单个 std::string 对象之前)。问题是如果y > 0,预分配的buffer会太小!

那么我怎么知道在使用arrayplacement-new时要预分配多少内存呢?

void* buffer = malloc(sizeof(std::string) * 10 + how_much_additional_space);
std::string* p = ::new (buffer) std::string[10];

或者在这种情况下,某处的标准是否保证 y == 0 ?再次,引用说:

This overhead may be applied in all array new-expressions, including those referencing the library function operator new[](std::size_t, void*) and other placement allocation functions.

最佳答案

更新

Nicol Bolas 在下面的评论中正确指出,此问题已得到修复,the overhead is always zero for operator new[](std::size_t, void* p) .

此修复是作为 defect report 完成的2019 年 11 月,这使得它可以追溯至所有 C++ 版本。

原答案

请勿使用 operator new[](std::size_t, void* p) 除非您先验地知道该问题的答案。答案是一个实现细节,可以随着编译器/平台而改变。尽管它对于任何给定平台通常都是稳定的。例如。这是 Itanium ABI 指定的内容.

如果你不知道这个问题的答案,写你自己的放置数组 new 可以在运行时检查这个:

inline
void*
operator new[](std::size_t n, void* p, std::size_t limit)
{
    if (n <= limit)
        std::cout << "life is good\n";
    else
        throw std::bad_alloc();
    return p;
}

int main()
{
    alignas(std::string) char buffer[100];
    std::string* p = new(buffer, sizeof(buffer)) std::string[3];
}

通过改变数组大小并检查上面示例中的 n,您可以推断出适合您平台的 y。对于 my platform y 是 1 个单词。 sizeof(word) 取决于我是针对 32 位还是 64 位架构进行编译。

关于c++ - 新数组放置需要缓冲区中未指定的开销?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8720425/

相关文章:

c++ - QtCreator : Loading External Library

c++ - 如何通过引用返回对象?

c++ - 为什么以下模板声明格式错误?

c++ - 为什么 `i =++i + 1` 未指定行为?

http - 为什么 HTTP 错误代码从 100 开始

c++ - 将 Hexdump 转换为 c 中的字符串

c++ - for_each 将字符串连接到 vector 中的所有字符串

c++ - 是 ISO/IEC 14882 :2011 the final draft?

linux-kernel - 如何确定 Linux 内核模块是否泄漏内存

c - C 中的 Abort Trap 6 错误和调试