我打开了-fsanitize=undefined
使用单元测试库Catch的项目。该标志表示从Catch发出一行信号导致未定义行为。我设法举了一个孤立的例子:
#include <iomanip>
#include <sstream>
int main()
{
std::ostringstream os;
os << "0x" << std::setfill('0') << std::hex;
}
编译:
clang++ -fsanitize=undefined main.cpp
如果运行此命令,则会显示以下打印:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/ios_base.h:96:24: runtime error: load of value 4294967221, which is not a valid value for type 'std::_Ios_Fmtflags'
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/ios_base.h:76:67: runtime error: load of value 4294967221, which is not a valid value for type 'std::_Ios_Fmtflags'
这对于我3.6.0
和clang都适用3.4-1ubuntu3
。我在gcc版本上不会发生4.9.2
那这里怎么了?这段代码实际上是错误的,还是在clang的末尾发生了一些麻烦?
这是libstdc ++中的一个错误,来自cfe-dev
标题为-fsanitize = undefined的邮件列表线程,共享库说:
这是libstdc ++中的错误。一旦Will的补丁登陆后,您就可以使用消毒剂黑名单文件解决该问题,但目前,手动将其过滤掉可能是您的最佳选择。
这是一个修复程序。我将在未来几天内将其推向libstdc ++上游。[...]
正如我指出这并非罕见的评论DYP看到系统中clang
使用libstdc++
,而不是libc++
如果我们测试这在Coliru明确使用的libstdc ++通过-stdlib=libstdc++
我们的确可以重现该问题。
以下libstdc++
错误报告:由ios_base.h中的operator〜计算的错误的枚举值涵盖了此问题,并说:
在ios_base.h中为枚举定义的重载运算符具有以下形式:
Enum operator~(Enum e) { return Enum(~static_cast<int>(e)); }
〜创建的值超出了枚举类型的值的范围,因此,强制转换为Enum类型的值没有指定(请参阅[expr.static.cast] p10),实际上,它产生的Enum值超出以下范围Enum类型的可表示值,因此行为未定义。
供参考[expr.static.cast] p10说:
整数或枚举类型的值可以显式转换为枚举类型。如果原始值在枚举值(7.2)的范围内,则该值不变。否则,结果值将不确定(并且可能不在该范围内)。浮点类型的值也可以转换为枚举类型。结果值与将原始值转换为枚举的基础类型(4.9)相同,随后又转换为枚举类型。
就像hvd所说的那样,这是形式上不确定的行为,但Richard指出,实际上这最终是不确定的行为。
TC指出,DR 1766将此行为从未指定行为更改为未定义行为:值超出枚举值范围:
尽管问题1094阐明了枚举类型的表达式的值可能不在转换为枚举类型后的枚举值的范围内(请参阅5.2.9 [expr.static.cast]第10段),但结果只是一个未指定的值。鉴于未定义的行为会使表达式变得非恒定,这一点可能应该得到加强,以产生未定义的行为。另请参见9.6 [class.bit]第4段。
新的措辞出现在N4431的标准草案中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句