如何鼓励C程序中未定义的行为/乱序执行?

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

我正在阅读以下关于C:https://www.geeksforgeeks.org/sequence-points-in-c-set-1/中的序列点的文章

在其中,有几个未定义行为的示例,例如调用两个修改单个全局变量的函数的表达式,或者多次递增同一个变量的单个表达式。

从理论上讲,我理解这个概念。但是,无论我尝试运行这些示例多少次,行为都是一样的,而且从不“令人惊讶”。

为了对未定义的行为进行实际操作,最简单的方法是让这些示例“令人惊讶”?

(如果重要,我使用的是MINGW64。)

c global-variables undefined-behavior unspecified-behavior
2个回答
0
投票

这是我能在短时间内提出的最佳方案:

源代码:

#include <stdio.h>

int undefined(int *a, short *b)
{
    *a = 1;
    b[0] = 0;
    b[1] = 0;
    return *a;
}

int main()
{
    int x;
    short *y = (short*) &x;
    int z = undefined(&x, y);
    printf("%d\n", z);
    return 0;
}

使用gcc 8.3 -O3进行组装

undefined(int*, short*):
    mov     DWORD PTR [rdi], 1
    mov     eax, 1
    mov     DWORD PTR [rsi], 0
    ret
.LC0:
    .string "%d\n"
main:
    sub     rsp, 8
    mov     esi, 1
    mov     edi, OFFSET FLAT:.LC0
    xor     eax, eax
    call    printf
    xor     eax, eax
    add     rsp, 8
    ret

看到它在行动:https://godbolt.org/z/E0XDYt

特别是,它依赖于将int的地址转换为short*所导致的未定义行为,这是一种打破严格别名规则的行为,因此会导致未定义的行为。

undefined()的组装开始。这假设由于ab是不同的类型,它们不能重叠,因此它将return *a;优化为mov eax,1,即使它从记忆中获取值实际上会返回零。它与优化关闭,所以这是一个真正隐蔽的问题,只在优化的发布版本中出现,而不是在您尝试使用非优化的调试版本进行调试时。

但是,请注意main()中的代码是如何尝试并使其正确的:它内联,然后优化掉对undefined()的调用,而是假设0中的z,当xor eax,eaxprintf的调用之上。因此,它忽略了它刚刚在上面的几行中找出的返回值,而是使用不同的值。

总而言之,这是一个非常糟糕的计划。究竟是什么风险与未定义的行为。


0
投票

测试gcc和clang时的一个有用模式是使用下标来访问数组,这些下标的值将在边界内,但编译器不知道,并使用标准描述为与下标表示法等效的指针语法。用以下方法测试gcc和clang:

struct S1 {int x;};
struct S2 {int x;};

union foo { struct S1 arr1[8]; struct S2 arr2[8]; } u;

uint32_t test1(int i, int j)
{
  if (sizeof u.arr1 != sizeof u.arr2)
    return -99;
  if (u.arr1[i].x)
    u.arr2[j].x = 2;
  return u.arr1[i].x;
}
uint32_t test2(int i, int j)
{
  if (sizeof u.arr1 != sizeof u.arr2)
    return -99;
  if ((u.arr1+i)->x)
    (u.arr2+j)->x = 2;
  return (u.arr1+i)->x;
}

将揭示尽管标准将u.arr1[i].xu.arr2[j].x的行为定义为分别等同于(u.arr1+i)->x(u.arr2+j)->x,但是当给予前者时,gcc和clang错过了一个允许的优化机会。这很可能是因为作者认识到利用前一个机会是可以允许的,但无可否认是愚蠢的,以至于强迫承认标准从未打算鼓励它允许的所有优化。

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