我有一个代码段from here:
volatile int volatileInt;
int usualInt;
void function (unsigned x, unsigned y, unsigned z)
{
volatileInt = 0;
usualInt = (x % y) / z;
}
int main()
{
function(rand(), rand(), rand());
}
我使用Visual C ++ 10编译/O2
并获得此反汇编:
00403940 push ebx
00403941 push esi
276: function(rand(), rand(), rand());
00403942 mov esi,dword ptr [__imp__rand (4050C0h)]
00403948 push edi
00403949 call esi
0040394B mov edi,eax
0040394D call esi
0040394F mov ebx,eax
00403951 call esi
00403953 xor edx,edx
00403955 div eax,ebx <<<< possible UB
00403957 mov dword ptr [volatileInt (4074D0h)],0
00403961 mov eax,edx
00403963 xor edx,edx
00403965 div eax,edi <<<< possible UB
00403967 pop edi
00403968 pop esi
00403969 pop ebx
0040396A mov dword ptr [usualInt (4074CCh)],eax
277: return 0;
0040396F xor eax,eax
00403971 ret
请注意,有两个操作 - “mod”和“div”,如果第二个操作数在运行时为零,则可能会产生UB。在发出的代码中,两个都使用div
操作码实现,这些操作码将触发结构化异常,并且程序崩溃,第二个操作数为零。
第一个div
位于修改volatile int
变量之前,但第二个位于修改volatile int
之后。
因此,如果x
为零,程序会在不修改volatile int
的情况下崩溃,但如果x
非零并且y
为零,则程序会修改volatile int
和然后崩溃。
因此,根据x
或y
是否为零,程序将表现出不同的可观察行为。
是否允许使用可能影响可观察行为的代码的代码与可能的UB进行交错?
答案 0 :(得分:7)
是的,允许此实现。见1.9 / 5:
执行格式良好的程序的符合实现应该产生与具有相同程序和相同输入的抽象机的相应实例的可能执行之一相同的可观察行为。但是,如果任何此类执行包含未定义的操作,则此国际标准不要求使用该输入执行该程序的实现(甚至不考虑第一个未定义操作之前的操作)。
答案 1 :(得分:5)
我认为第1.9:4条与此相关:
本国际标准中描述的某些其他操作未定义(例如,效果 尝试修改const对象)。 [注:本国际标准没有规定 包含未定义行为的程序的行为。 - 后注]
据我了解,这意味着如果程序执行最终导致未定义的行为,那么程序的整个可观察行为是未定义的。