为什么 bitset::set() 会触发未定义的行为

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

如果我编译这段代码

#include <bitset>

int
main(int argc, char** argv) {
    std::bitset<96> mask;
    mask.set();
    return 0;
}

clang++ -fsanitize=integer test_bitset.cpp
运行结果,我得到

.../include/c++/12/bitset:657:46: runtime error: left shift of 18446744073709551615 by 32 places cannot be represented in type 'std::_Sanitize::_WordT' (aka 'unsigned long')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior .../include/c++/12/bitset:657:46 in 

这看起来有点像为什么 clang sanitizer 认为无符号数的左移是未定义的? 但如果我尝试使用

禁用检查
clang++ -fsanitize=integer -fno-sanitize=unsigned-integer-overflow test_bitset.cpp

未定义的行为仍然存在。为了增加混乱,如果我手动启用“所有”整数检查(如文档中所述)

clang++ -fsanitize=signed-integer-overflow,unsigned-integer-overflow,shift,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change test_bitset.cpp 

未定义的行为消失了。那么显然

-fsanitize=integer
的作用还不止于此?

我可以使用位集上的黑名单来消除错误,但我真的想知道它是否是 stdlib 中的错误或可以安全地忽略。

我在标准 ubuntu 22.04 上用 clang 14 和 clang 15 尝试了这个。任何提示表示赞赏。

c++ clang++ std-bitset ubsan
1个回答
0
投票

正如 @user17732522 正确指出的那样,这只是 clang 文档中的一个错误。避免检查的正确调用是

clang++  -fsanitize=integer -fno-sanitize=unsigned-shift-base test_bitset.cpp
,而检查只是过于敏感,它不是是未定义的行为。

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