c - 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)
;
}
}
解决方案
因此,实际问题是在空语句上遇到断点,其中if
条件被评估为假。
这不是“失败”:观察到的程序行为是相同的,编译器可能会发出任何指令来匹配观察到的行为。启用的优化越多,编译器就越会“转换”程序。
有一种解决方法来插入__nop()
内在函数。编译器会发出一个字节的无目的指令,但不会忽略它,并使控制流公平。这是拥有编译器不会优化的东西的最轻量级的方法。
#include <stdio.h>
#include <intrin.h>
int main(void)
{
for (;;)
if (fwrite("Foo", 3, 1, stdout) != 1)
__nop();
}
请注意,将这个内在函数添加到程序中可能会使代码的优化程度稍差一些,这主要不是由额外的指令引起的,而是由编译器在转换程序时造成的。对于您的情况,编译器很可能会丢弃整个!= 1
比较,但不会使用__nop()
.
推荐阅读
- java - 方法参考适用于 Comparator.comparing 方法,而 lambda 表达式不起作用
- c - C中贪心算法的输出没有给我任何输出
- javascript - 更改许多父属性而不将它们全部写出来
- linux - 如何在 rrdtool 图中按时间段聚合数据
- python - 重新采样数据帧,插入 NaN 并返回数据帧
- laravel - 使用 Sendinblue 从 Laravel 应用程序发送数据
- javascript - formik 组件正在将文本类型的受控输入更改为不受控制
- android - 如何使用 Toothpick 对 android ViewModels 使用构造函数注入
- reactjs - 条件反应属性
- java - Java DerInputStream.getLength():lengthTag=109