在发布模式下,代码行为不符合预期

2023-12-27

以下代码在调试模式和发布模式下产生不同的结果 (使用 Visual Studio 2008):

int _tmain(int argc, _TCHAR* argv[])
{

    for( int i = 0; i < 17; i++ ) 
    { 
        int result = i * 16;

        if( result > 255 )
        {
            result = 255;
        }

        printf("i:%2d, result = %3d\n", i, result) ; 
    } 

    return 0;
}

调试模式的输出,符合预期:

i: 0, result =   0
i: 1, result =  16
(...)
i:14, result = 224
i:15, result = 240
i:16, result = 255

释放模式的输出,其中 i:15 结果不正确:

i: 0, result =   0
i: 1, result =  16
(...)
i:14, result = 224
i:15, result = 255
i:16, result = 255

在Visual Studio发布模式下选择“优化->不优化”,输出结果将是正确的。但是我想知道为什么优化过程会导致错误的输出。


Update:

根据 Mohit JainBy 的建议,打印者:

printf("i:%2d, result = %3d, i*16=%d\n", i, result, i*16) ;

释放模式输出正确:

i: 0, result =   0, i*16=0
i: 1, result =  16, i*16=16
(...)
i:14, result = 224, i*16=224
i:15, result = 240, i*16=240
i:16, result = 255, i*16=256

这很有趣,至少从历史的角度来看。我可以使用 VC 2008 (15.00.30729.01) 重现该问题andVC 2010 (16.00.40219.01)(针对 32 位 x86 或 64 位 x64)。我从 VC 2012 (17.00.61030) 开始尝试的任何编译器都不会出现此问题。

我用来编译的命令:cl /Ox vc15-bug.cpp /FAsc

由于 VC 2008(和 2010)相当旧,而且修复已经进行了好几年了,我认为除了使用更新的编译器之外,您不能指望 Microsoft 采取任何行动(尽管也许有人可以建议解决方法)。

问题是确定该值是否应该被强制进行测试255是根据循环计数而不是实际结果完成的i * 16表达。当编译器应该开始强制该值时,编译器只是得到了错误的计数。255。我不知道为什么会发生这种情况 - 这只是我看到的效果:

; 6    :    for( int i = 0; i < 17; i++ ) 

  00001 33 f6        xor     esi, esi
$LL4@main:
  00003 8b c6        mov     eax, esi
  00005 c1 e0 04     shl     eax, 4

; 7    :    { 
; 8    :        int result = i * 16;
; 9    : 
; 10   :        if( result > 255 )

  // the value `esi` is compared with in the following line should be 15!
  00008 83 fe 0e     cmp     esi, 14            ; 0000000eH
  0000b 7e 05        jle     SHORT $LN1@main

; 11   :        {
; 12   :            result = 255;

  0000d b8 ff 00 00 00   mov     eax, 255       ; 000000ffH
$LN1@main:

; 13   :        }

Update:我安装的 VC 2008 之前的所有 VC 版本都有相同的错误,除了 VC6 - 编译程序会使 VC6 编译器崩溃:

vc15-bug.cpp(10) : fatal error C1001: INTERNAL COMPILER ERROR

所以这是一个在 MSVC 中以某种形式持续了 10 多年的 bug!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在发布模式下,代码行为不符合预期 的相关文章

  • 编写此代码片段的有效方法是什么? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 更有效和 或更短地重写此代码以节省字节并显得不那么冗长的方法 if N 2 0 N 6 N 8 N 10 N 12 N 14 N 16 N
  • 如何使用 ASP.NET MVC 编辑多选列表?

    我想编辑一个如下所示的对象 我希望用 UsersGrossList 中的一个或多个用户填充 UsersSelectedList 使用 mvc 中的标准编辑视图 我只得到映射的字符串和布尔值 下面未显示 我在 google 上找到的许多示例都
  • 元组在 VS2012 中如何工作?

    Visual Studio 2012 功能 tuples但不是可变参数模板 这是如何完成的 如何在不使用可变模板的情况下实现元组 简而言之 微软做了与之前在 NET 中实现类似元组的数据类型完全相同的事情 创建许多版本 每个版本都有固定数量
  • c# 从另一个类中的另一个静态事件引发事件

    需要帮助从另一个班级调用事件 我有已声明事件的课程 public class MxPBaseGridView GridView public event AddNewItemsToPopUpMenuEventHandler AddNewIt
  • 锁定 ASP.NET 应用程序变量

    我在 ASP NET 应用程序中使用第三方 Web 服务 对第 3 方 Web 服务的调用必须同步 但 ASP NET 显然是多线程的 并且可能会发出多个页面请求 从而导致对第 3 方 Web 服务的同时调用 对 Web 服务的调用封装在自
  • 将设置函数(setter)标记为 constexpr 的目的是什么? [复制]

    这个问题在这里已经有答案了 我无法理解将 setter 函数标记为的目的constexpr 自 C 14 起这是允许的 我的误解来自以下情况 我使用 constexpr c tor 声明一个类 并且我将通过创建该类的 constexpr 实
  • 如何以编程方式播放 16 位 pcm 数组 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有一个包含 16 位 pcm 值的短 数组 我希望能够在不添加任何标题 也不将任何文件保存到内存的情况下播放它 我知道我可能需要一个提供
  • while循环中的变量初始化

    我有一个可以分块读取文件的函数 public static DataObject ReadNextFile 数据对象看起来像这样 public DataObject public string Category get set And ot
  • C# 编译器数字文字

    有谁知道 C 编译器数字文字修饰符的完整列表 默认情况下 声明 0 使其成为 Int32 声明 0 0 使其成为 Double 我可以在末尾使用文字修饰符 f 来确保某些内容被视为 Single 例如像这样 var x 0 x is Int
  • 通过 C# Mailkit / Mimekit 发送电子邮件,但出现服务器证书错误

    Visual Studio 2015 中的 0 代码 1 我正在使用 Mailkit 最新版本 1 18 1 1 从我自己的电子邮件服务器发送电子邮件 2 电子邮件服务器具有不受信任的自签名证书 3 我在代码中添加了以下两行 以忽略服务器证
  • 时间:2019-03-17 标签:c++fstream并发访问

    如果从不同的进程 线程同时访问文件会发生什么 据我所知 没有锁定文件的标准方法 只有操作系统特定的功能 就我而言 文件将被经常读取而很少写入 现在如果A打开一个文件进行读取 ifstream 并开始读取块 和B打开相同的文件进行写入 ofs
  • 使用 OleDbCommandBuilder 时访问 SQL 语法错误

    我要在 C 中使用 OleDbDataAdapter 在 Access 数据库中插入数据 但收到错误消息INSERT INTO 命令中的语法错误 BackgroundWorker worker new BackgroundWorker Ol
  • 将错误代码映射到 C++ 中的字符串

    将错误代码从枚举映射到字符串的更有效方法是什么 在 C 中 例如 现在我正在做这样的事情 std string ErrorCodeToString enum errorCode switch errorCode case ERROR ONE
  • C++ 到 C# 事件处理

    所以我有我的C WinForm 应用程序 我从中调用我的C CLI MFC dll图书馆 但也有一些events在我的 C 库上 甚至此事件也发生在该库的本机 非 CLI 部分 我需要从我的 C 应用程序调用一些代码 并获取一些有关此事件的
  • C 中使用 getrandom 实现随机浮点数

    我试图生成一个介于 0 和 1 之间的随机浮点数 无论是在 0 1 还是 0 1 对我来说都不重要 网上关于此的每个问题似乎都涉及rand 呼叫 播种time NULL 但我希望能够每秒多次调用我的程序 并每次都获得不同的随机数 这引导我找
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟
  • Linq.Select() 中的嵌套表达式方法调用

    I use Select i gt new T 每次手动点击数据库后将我的实体对象转换为 DTO 对象 以下是一些示例实体和 DTOS 用户实体 public partial class User public int Id get set
  • 如何将 int 作为“void *”传递给线程启动函数?

    我最初有一个用于斐波那契变量数组的全局变量 但发现这是不允许的 我需要进行基本的多线程处理并处理竞争条件 但我无法在 pthread 创建中将 int 作为 void 参数提供 我尝试过使用常量指针 但没有成功 由于某些奇怪的原因 void
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost
  • 嵌入式二进制资源 - 如何枚举嵌入的图像文件?

    我按照中的说明进行操作这本书 http www apress com book view 9781430225492 关于资源等的章节 我不太明白的是 如何替换它 images Add new BitmapImage new Uri Ima

随机推荐

  • 在PHP中,为什么我能够以静态方式访问非静态方法?

    在以下代码中 nonStatic 不是静态方法 即使如此 我也可以在不创建对象的情况下访问它 以静态方式 谁能帮助我理解 因为这在其他语言 如 Java 中是不可能的
  • 从 docker Inspection 获取标签值[重复]

    这个问题在这里已经有答案了 由于键有 我无法从地图列表中获取值 里面 docker inspect jenkins Config Labels com docker compose config hash 85bcf1e0bcd708120
  • NumPy 中 ndim 的真正作用是什么? [复制]

    这个问题在这里已经有答案了 考虑 import numpy as np gt gt gt a np array 1 2 3 4 gt gt gt a array 1 2 3 4 gt gt gt a ndim 1 维度1如何 我给出了三个变
  • 你能为 Ruby 中的 map(&:method) 语法提供参数吗?

    您可能熟悉以下 Ruby 简写 a是一个数组 a map method 例如 在 irb 中尝试以下操作 gt gt a a a 1 1 0 gt a a 1 1 0 gt gt a map class gt Symbol String F
  • 一个输入有多个验证器

    JSF 2 0 中的一个输入是否可以有多个验证器 例如 假设我要写一个用户名 并且用户名必须有 8 个字符 如果OK 则检查数据库中是否不存在该用户名
  • Epson POS 打印机 - 自动状态返回规格

    我正在尝试解释 Epson POS 打印机的自动状态返回 ASB 数据 我已使用 UB E20 技术参考指南 www amigopos com faq faq 262 aspx 中的一些示例代码成功与打印机取得联系 不幸的是 手册只说明了我
  • iOS 报亭:推送通知不会在后台启动应用程序

    我正在应用程序中实现报刊亭功能 尽管应用程序收到推送通知 但它不会在后台模式下启动 如果我点击通知警报 应用程序将启动 我可以看到字典中存在 content available 1 并且该问题已下载 但应用程序不会自动启动 我已添加到 pl
  • 使用 twitter bootstrap typeahead 时如何禁用 google chrome 建议列表?

    使用 twitter bootstrap typeahead 我在 typeahead 列表上方得到 google chrome 建议列表 document ready function ID TextBox typeahead sourc
  • Docker 使用 gosu 与 USER

    Docker有点总是有一个USER命令以特定用户身份运行进程 但一般来说很多事情必须以 ROOT 身 份运行 我见过很多使用ENTRYPOINT with gosu取消提升进程的运行权限 我仍然对是否需要感到有点困惑gosu USER 还不
  • 在Unity中使用抽象工厂作为注入工厂?

    我有一个抽象工厂注册用于在某些控制器实例中注入 我可以注册该抽象工厂并将其用作注入工厂吗 这就是我所拥有的 public interface ILevelFactory Levels Create RegisterType
  • 紧凑框架语音识别API或库

    到目前为止 我的研究告诉我 没有免费的语音识别库 这仍然是这种情况吗 因为我发现的所有帖子都是几年前的 如果我想让我的 WinMobile C 应用程序能够 是否有示例应用程序或任何我可以开始的东西 从输入中识别语音 看一下http www
  • 获取curl php中最后一个重定向的url

    大家好 我知道这是 StackOverFlow 上一个非常常见的话题 我已经花了整整一周的时间来寻找它 我有一个网址 abc com default asp strSearch 19875379 这进一步重定向到此网址 abc com de
  • 在 AngularJS 中观察外部变量?

    我已经为 Chrome 应用程序中的串行通信编写了一个小型 JS 库 并且它本身运行良好 然而 我们在与 Angular 集成时遇到了一个问题 我没有办法从内部观察控制器外部串行对象的属性 而且我也无法找到解决方法 理想情况下 有一个计算成
  • 使用 plist 创建测验的随机整数

    我想让用户单击一个按钮以 a b c 的形式生成十个问题测验 其中 a 和 b 的值从 10 到 10 并随机分配给十个问题 此外 问题应该在加法和减法之间随机切换 如何正确填充 plist 文件 我该如何使用arc4random用随机整数
  • 如何使用 libgit2sharp 获取文件的先前版本

    我正在尝试使用libgit2sharp获取文件的先前版本 我希望工作目录保持原样 至少恢复到以前的状态 我最初的方法是尝试存储 签出我想要的文件的路径 将其保存到字符串变量 然后存储弹出 有没有办法隐藏流行音乐 我不容易找到它 这是我到目前
  • 以主题作为文件名保存邮件

    大家早上好 我希望有人可以帮助我编写一段代码 我希望将选定的电子邮件保存到特定目录 并使用电子邮件的名称 当然还有 msg 文件 这就是我今天所拥有的 但它不起作用 它保存一个文件 但名称只有前 2 个字符 看起来在分号文件名后出错 例如
  • xkcd:外部性

    所以2013年4月1日 xkcd外部性 http xkcd com 1193 网络漫画以 Skein 1024 1024 哈希破解为特色contest http almamater xkcd com 我假设这一定只是一种暴力行为 其中随机字
  • OxyPlot:如何隐藏左侧和顶部轴线

    我在 Xamarin iOS 项目中使用 Oxyplot 来绘制条形图 这就是我的情节目前的样子 这里我需要隐藏右轴和顶轴 我试过 model Axes Add new LinearAxis Position AxisPosition Ri
  • “无法识别的选择器发送到实例”UINavigationController

    我的 Xcode 应用程序收到以下异常错误消息 UINavigationController setDeals unrecognized selector sent to instance 0x8338d40 在以下上下文中抛出异常prep
  • 在发布模式下,代码行为不符合预期

    以下代码在调试模式和发布模式下产生不同的结果 使用 Visual Studio 2008 int tmain int argc TCHAR argv for int i 0 i lt 17 i int result i 16 if resu