6

ここからコードスニペットがあります:

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());
}

これをVisualC++ 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」の2つの演算があり、実行時に2番目のオペランドがゼロの場合にUBを生成する可能性があることに注意してください。放出されたコードでは、両方ともdiv構造化例外をトリガーしてプログラムをクラッシュさせるオペコードで実装されています。第2オペランドはゼロです。

1つ目は変数が変更さdivれる前ですが、2つ目は変更後です。volatile intvolatile int

したがって、xがゼロの場合、プログラムは変更せずにクラッシュしますvolatile intが、xがゼロ以外でyゼロの場合、プログラムは変更volatile intされてからクラッシュします。

したがって、ゼロであるかゼロであるかに応じてxyプログラムは異なる観察可能な動作を示します。

観察可能な動作に影響を与えるコードを含む可能性のあるUBとのコードのそのようなインターリーブは許可されていますか?

4

2 に答える 2

7

はい、この実装は許可されています。1.9/5を参照してください。

整形式のプログラムを実行する適合実装は、同じプログラムと同じ入力を持つ抽象マシンの対応するインスタンスの可能な実行の1つと同じ観察可能な動作を生成する必要があります。ただし、そのような実行に未定義の操作が含まれている場合、この国際規格では、その入力を使用してそのプログラムを実行する実装に要件はありません(最初の未定義の操作に先行する操作に関しても)。

于 2012-07-18T09:37:51.127 に答える
5

1.9:4節はここに関連していると思います:

他の特定の操作は、この国際規格では未定義として説明されています(たとえば、constオブジェクトを変更しようとする効果)。[注:この国際規格は、未定義の動作を含むプログラムの動作に要件を課していません。—エンドノート]

私が理解しているように、これは、プログラムの実行が最終的に未定義の動作をもたらす場合、プログラムの観察可能な動作全体が未定義であることを意味します。

于 2012-07-18T09:28:37.073 に答える