Visual Studio C 程序 运行 使用 VS 编译器失败但使用 Clang
Visual Studio C program run fails with VS compiler but works with Clang
配置:Win10 64 位,安装了所有更新和 Clang v12.0 的 VS2019,并在 null 语句上设置了断点。
如果使用 VS 编译器编译,下面的第一个版本的代码会在 Foo 第一次输出到控制台后命中断点,但如果使用 Clang 编译,则会按预期循环。第二个版本按预期使用 VS 编译器和 Clang 循环。如果我删除断点,两个版本都会按预期使用两个编译器循环。为什么断点会导致第一个版本与 VS 编译器一起失败?
版本 1:
#include <stdio.h>
int main(void)
{
for (;;)
if (fwrite("Foo", 3, 1, stdout) != 1)
;
}
版本 2:
#include <stdio.h>
int main(void)
{
for (;;)
{
if (fwrite("Foo", 3, 1, stdout) != 1)
;
}
}
因此,实际问题是在空语句上遇到断点,其中 if
条件被评估为 false。
这不是“失败”:观察到的程序行为是相同的,编译器可能发出任何指令来匹配观察到的行为。启用的优化越多,编译器就越能“改造”程序。
有一种解决方法可以插入 __nop()
内在函数。编译器会发出一字节的无目的指令,但不会忽略它,并且会使控制流公平。这是拥有编译器不会优化掉的东西的最轻量级方法。
#include <stdio.h>
#include <intrin.h>
int main(void)
{
for (;;)
if (fwrite("Foo", 3, 1, stdout) != 1)
__nop();
}
请注意,将此内在函数添加到程序中可能会使代码的优化程度略有下降,这主要不是由额外的指令引起的,而是由于限制了编译器转换程序造成的。对于您的情况,编译器很可能会丢弃整个 != 1
比较,但不会对 __nop()
.
进行比较
配置:Win10 64 位,安装了所有更新和 Clang v12.0 的 VS2019,并在 null 语句上设置了断点。
如果使用 VS 编译器编译,下面的第一个版本的代码会在 Foo 第一次输出到控制台后命中断点,但如果使用 Clang 编译,则会按预期循环。第二个版本按预期使用 VS 编译器和 Clang 循环。如果我删除断点,两个版本都会按预期使用两个编译器循环。为什么断点会导致第一个版本与 VS 编译器一起失败?
版本 1:
#include <stdio.h>
int main(void)
{
for (;;)
if (fwrite("Foo", 3, 1, stdout) != 1)
;
}
版本 2:
#include <stdio.h>
int main(void)
{
for (;;)
{
if (fwrite("Foo", 3, 1, stdout) != 1)
;
}
}
因此,实际问题是在空语句上遇到断点,其中 if
条件被评估为 false。
这不是“失败”:观察到的程序行为是相同的,编译器可能发出任何指令来匹配观察到的行为。启用的优化越多,编译器就越能“改造”程序。
有一种解决方法可以插入 __nop()
内在函数。编译器会发出一字节的无目的指令,但不会忽略它,并且会使控制流公平。这是拥有编译器不会优化掉的东西的最轻量级方法。
#include <stdio.h>
#include <intrin.h>
int main(void)
{
for (;;)
if (fwrite("Foo", 3, 1, stdout) != 1)
__nop();
}
请注意,将此内在函数添加到程序中可能会使代码的优化程度略有下降,这主要不是由额外的指令引起的,而是由于限制了编译器转换程序造成的。对于您的情况,编译器很可能会丢弃整个 != 1
比较,但不会对 __nop()
.