Visual Studio 优化破坏了 SDL 图形输出

Visual Studio optimisations break SDL graphical output

在编译我的 Chip-8 仿真器时,它在 Visual Studio 中使用 SDL-2 并进行了优化,SDL window 无法显示任何图形。 SDL window 在没有优化的情况下编译时完全工作。

我已经反汇编了二进制文件,看看我是否能弄清楚优化器到底在做什么,反汇编时优化代码和未优化代码之间的唯一区别是两条 rdata 行,如下所示:

优化:

.rdata:140006914 2f                               0x2f '/'
.rdata:140006915 55                               0x55 'U'

未优化:

.rdata:140006914 ce                               0xce 
.rdata:140006915 56                               0x56 'V'

我对 x86 汇编没有太多经验,所以不明白这种差异会带来什么以及为什么它会破坏东西。

此外,恢复到我认为有效的先前提交以相同的方式中断,并且使用先前编译的有效的二进制文件也是如此。这让我想知道这是否可能是来自 Windows.

的问题

这两条 rdata 行究竟如何对应用程序产生如此显着的影响,我将如何解决这个问题?

我不确定确切的问题,但是...

当编译器看到这样的东西时:

int loopDisplay(void) {
    while (running) {
        if (chip8.drawFlag) {
            UpdateDisplay();              // Update Display
            chip8.drawFlag = false;       // Reset Draw Flag
        }
    }
    return 0;
}

它会查找像 chip8.drawFlag 这样的变量的详细信息,意识到它没有什么特别的(它是一个普通的 boolean drawFlag;);然后优化代码使其更像这样(其中 temp 可能只是 CPU 寄存器之一中的值):

int loopDisplay(void) {
    temp = chip8.drawFlag;
    while (running) {
        if (temp) {
            UpdateDisplay();              // Update Display
            temp = false;                 // Reset Draw Flag
        }
    }
    chip8.drawFlag = temp;
    return 0;
}

然后它会意识到它可以进一步优化它,也许会想出这样的东西:

int loopDisplay(void) {
    temp = chip8.drawFlag;
    if(running && temp) 
         UpdateDisplay();              // Update Display
        }
    }
    while(running) {}
    chip8.drawFlag = false;
    return 0;
}

当然,如果 running 也只是一个普通的旧变量,那么它可以决定该函数要么什么也不做并立即 return,要么永远循环(并且永远不会执行 chip8.drawFlag = false 永远不会 return).

要解决这类问题(2 个或更多线程在没有任何同步的情况下使用相同的东西),您需要告诉编译器变量是特殊的(例如,在使用它们之前获取锁,或者使它们成为原子)。您必须检查所有代码并找出所有问题。