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