陷阱表示,unsigned char和IA64 NaT

来源:ia64上未初始化的垃圾可能致命

在ia64上,每个64位寄存器实际上是65位。 额外的位被称为“NaT”,代表“不是一件事”。 当寄存器不包含有效值时,该位置1。 可以将其视为浮点NaN的整数版本。

NaT位最常见于推测执行。 在ia64上有一种特殊forms的加载指令,它试图从内存中加载值,但是如果加载失败(因为内存被分页或地址无效),那么所有发生的事情都会发生,而不是引发页面错误是NaT位被设置,并继续执行。

NaT的所有数学运算都会再次产生NaT。

源文章接着解释了寄存器在推测加载过程中如何最终得到NaT表示并做出如下注释:

如你所见,如果你有一个值为NaT的寄存器,并且你以错误的方式呼吸(例如,尝试将其值保存到内存中),处理器将引发STATUS_REG_NAT_CONSUMPTIONexception。

似乎从陷阱表示的其他堆栈溢出答案,
“任何类型(unsigned char除外)都可能有陷阱表示”。

这个链接说明了

标准给出的关于访问未初始化数据的唯一保证是unsigned char类型没有陷阱表示,并且该padding没有陷阱表示。

如果这样的寄存器(具有NaT位设置的寄存器)被分配用于存储未初始化的无符号字符(类似于下面的缺陷报告中的代码片段),那么如何根据ISO C11处理?

以下缺陷报告是否指向同一问题,是否在ISO C11中得到纠正?

如果不是如何处理这种特殊情况?

如果左值指定了一个自动存储持续时间的对象,该对象可能已经使用寄存器存储类声明(从未使用过其地址),并且该对象未初始化(未使用初始化程序声明,并且未对其进行任何赋值)使用),行为未定义

在“更改为C1X”部分的缺陷报告末尾添加上述内容是否处理此案例?

defect_report

以下函数在C90下具有未定义的行为,但在C99下似乎严格符合

int foo(void) { unsigned char uc; return uc + 1 >= 0; } 

首先,如果你还没有亲眼看到它,你可以从这里获取C11标准的最终草案( 另见 )。

来自DR的文本确实被添加到第6.3.2.1节p2中,这使得代码根据C11未定义。

关于陷阱表示的标准中的部分继续排除unsigned char可以具有陷阱表示的可能性 – 但这无关紧要。 这里需要注意的是,正如DR提到的2008年春季记录所提到的那样,从标准的角度来看,这实际上并不需要涉及陷阱表示本身(它们只是UB可能引起的一种机制)金属上的问题)。 问题实际上是关于未初始化的自动值; 修改后的段落解释了这一点,澄清了unsigned char不应仅仅因为其特定类型的属性之一 被视为免除一般类型的UB(而不是通过为该属性添加更多复杂性)。

你可以想象,就像NaT位是IA64上整数的实现细节一样,陷阱表示的缺失是C类通用族中一种特定类型的“实现细节”。 变量的实际类型是次要的一般规则,您不应该感到安全访问任何未初始化的变量; 添加澄清了优先权。