在下面的代码中
struct alignas(8) SimpleChar {
SimpleChar(char c_) : c(c_) {}
char c;
};
int main() {
char slab[10] = {'\0'};
// call to 'SimpleChar::SimpleChar(char)' too
SimpleChar* c0 = new (slab) SimpleChar('a');
SimpleChar* c1 = new (slab + 8) SimpleChar('b');
SimpleChar* c2 =
new (std::launder(reinterpret_cast<char*>(slab + 80))) SimpleChar('d'); // But how to detect the wrong usage?
std::cout << c2->c << std::endl; // d
SimpleChar* c3 = new (slab + 180) SimpleChar('e'); // But how to detect the wrong usage?
std::cout << c3->c << std::endl; // e
}
c2
和 c3
构建在错误的位置。但如何检测呢?
在这种情况下,valgrind和-fsanitize=address
都不起作用。
我想知道如何检测这种错误的用法?
根据您显示的选项,我假设您使用 GCC 或 Clang。
在这种情况下,
-fsanitize=undefined
,特别是-fsanitize=alignment
,都会抱怨两者,因为示例中的偏移量与类型不对齐。
事实上,一般来说,你的所有展示位置新闻都有 UB,因为不能保证
slab
与 8
对齐。如果您想在其中存储 alignas(SimpleChar)
,您还需要将 SimpleChar
添加到其声明中。
在 Clang
-fsanitize=undefined
上,特别是 -fsanitize=array-bounds
,也会抱怨存储阵列上的访问越界。
GCC 似乎不支持
array-bounds
UB 消毒剂检查,而是抱怨 -Wall
中包含警告,特别是 -Wplacement-new
。
(此外,从技术上讲,用于为其他对象提供存储的数组应该具有元素类型
unsigned char
或 std::byte
,而不是 char
。)