Placement new是写入比数组大小更多的字节

时间:2017-10-11 20:07:10

标签: c++

在下面的程序中,我希望用placement new覆盖10个字节,然后为每个字节调用析构函数:

#include <memory>

struct MyChar {
    MyChar(char c = 'n') :c{c}{}
    ~MyChar(){ c = 'd'; }
    char c;
};

int main()
{
    {
        MyChar first[10]{0,1,2,3,4,5,6,7,8,9};
        new (first)MyChar[10]{10,11,12,13,14,15,16,17,18,19};
    }
    return 0;
}

但编译器(*)警告将写入18:

  

警告C6386:写入&#39;第一个&#39;:可写的缓冲区溢出   大小是&#39; 10&#39;字节,但&#39; 18&#39;可能会写入字节。

首先,字节按预期写入: enter image description here

但是编译器并没有虚张声势。在放置新语句时,它写入18个字节: enter image description here

导致错误:

  

运行时检查失败#2 - 堆叠变量&#39; first&#39;是   损坏。

为什么它不会坚持10个字节? sizeof(MyChar)==1alignof(MyChar)==1

(*)Microsoft Visual Studio社区2017预览版(2)。另外(但在编译期间没有警告)我在Microsoft Visual Studio Community 2017(版本15.2(26430.15)版本)上获得了相同的内存覆盖和运行时错误。

1 个答案:

答案 0 :(得分:4)

放置新数组可能需要比N * sizeof(Object)

更多的位置

(因为编译器必须能够使用delete[]正确调用析构函数???)。

  

5.3.4 [expr.new]:

     

new(2,f) T[5]会调用operator new[](sizeof(T)*5+y,2,f)

     

此处,xy是非负的未指定值,表示数组分配开销; new-expression的结果将由operator new[]返回的值抵消此金额。此开销可以应用于所有数组新表达式,包括引用库函数operator new[](std::size_t, void*)和其他放置分配函数的表达式。开销的数量可能因新的一次调用而异。 - 例子]