使用placement new操作符时如何检查是否超出范围?

问题描述 投票:0回答:1

在下面的代码中

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
都不起作用。

我想知道如何检测这种错误的用法?

c++ c++17 valgrind placement-new
1个回答
1
投票

根据您显示的选项,我假设您使用 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
。)

© www.soinside.com 2019 - 2024. All rights reserved.