首页 > 解决方案 > Visual Studio C 程序使用 VS 编译器运行失败,但使用 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)
         ;
   }
}

标签: cvisual-studioclangvisual-studio-2019

解决方案


因此,实际问题是在空语句上遇到断点,其中if条件被评估为假。

这不是“失败”:观察到的程序行为是相同的,编译器可能会发出任何指令来匹配观察到的行为。启用的优化越多,编译器就越会“转换”程序。

有一种解决方法来插入__nop()内在函数。编译器会发出一个字节的无目的指令,但不会忽略它,并使控制流公平。这是拥有编译器不会优化的东西的最轻量级的方法。

#include <stdio.h>
#include <intrin.h>

int main(void)
{
    for (;;)
        if (fwrite("Foo", 3, 1, stdout) != 1)
            __nop();
}

请注意,将这个内在函数添加到程序中可能会使代码的优化程度稍差一些,这主要不是由额外的指令引起的,而是由编译器在转换程序时造成的。对于您的情况,编译器很可能会丢弃整个!= 1比较,但不会使用__nop().


推荐阅读