在下面的程序中,我希望用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;可能会写入字节。
但是编译器并没有虚张声势。在放置新语句时,它写入18个字节:
导致错误:
运行时检查失败#2 - 堆叠变量&#39; first&#39;是 损坏。
为什么它不会坚持10个字节? sizeof(MyChar)==1
和alignof(MyChar)==1
。
(*)Microsoft Visual Studio社区2017预览版(2)。另外(但在编译期间没有警告)我在Microsoft Visual Studio Community 2017(版本15.2(26430.15)版本)上获得了相同的内存覆盖和运行时错误。
答案 0 :(得分:4)
放置新数组可能需要比N * sizeof(Object)
(因为编译器必须能够使用delete[]
正确调用析构函数???)。
5.3.4 [expr.new]:
new(2,f) T[5]
会调用operator new[](sizeof(T)*5+y,2,f)
。此处,
x
和y
是非负的未指定值,表示数组分配开销; new-expression的结果将由operator new[]
返回的值抵消此金额。此开销可以应用于所有数组新表达式,包括引用库函数operator new[](std::size_t, void*)
和其他放置分配函数的表达式。开销的数量可能因新的一次调用而异。 - 例子]