hrefspace

 找回密码
 立即注册
搜索
热搜: PHP PS 程序设计
查看: 636|回复: 9

发现微软编译器三路比较运算()的一个大 bug!

[复制链接]

481

主题

481

帖子

1465

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1465
发表于 2023-11-1 09:15:42 | 显示全部楼层 |阅读模式
有符号的大整数加减法,最终都会进行无符号的加减法。
而无符号的减法,必须得是较大者作为被减数,也就是说得先有个比较运算。

而就是这一步,曾害得我花了好几个小时去排查一个 bug,最终居然是微软编译器的问题!
  1. // test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include "pch.h"#include <compare>#include <iostream>// 2020-03-16, gxqcn 发现编译器 bug: 如写成 const auto cmp{ *--pl <=> *--pr }, 当 0 != cmp 时,指针会多移动一次!int main(){    const auto test{ []( auto a, auto b )    {        std::cout << "before compare: a=" << a << " b=" << b << "\n";        const auto cmp{ a++ <=> b++ };        std::cout << "after  compare: a=" << a << " b=" << b << "\n\n";        // 为了对比检测 std::max() 是否有类似表现,        std::cout << "std::max( a++, b++ ) = " << std::max( a++, b++ ) << "\n";        std::cout << "after  std::max: a=" << a << " b=" << b << "\n\n";    }};    test( 1, 1 );   // 测试表明:当相等时,表现与预期相符    test( 1, 2 );   // 测试表明:当不等时,表现与预期不符    std::cout << "-------------------------\n\n";    int v1[]{ 1, 2, 3, 4, 5, 6 };    int v2[]{ 1, 2, 0, 9, 0, 6 };    auto p1{ std::cbegin( v1 ) - 1 };    auto p2{ std::cbegin( v2 ) - 1 };    std::cout << "compare: v1{ 1, 2, 3, 4, 5, 6 } <=> v2{ 1, 2, 0, 9, 0, 6 }\n\n";    for ( auto index{ 0 }; sizeof( v1 ) / sizeof( v1[ 0 ] ) != index; ++index )    {        if ( const auto cmp{ *++p1 <=> *++p2 }; 0 != cmp )        {            std::cout << "v1[" << index << "] = " << v1[ index ] << "; *p1 =" << *p1 << "\n";            std::cout << "v2[" << index << "] = " << v2[ index ] << "; *p2 =" << *p2 << "\n";            if ( 0 < cmp )            {                std::cout << "\nv1 > v2";            }            else            {                std::cout << "\nv1 < v2";            }            if (( v1[ index ] <=> v2[ index ] ) == cmp )            {                std::cout << ", it's right.\n\n";            }            else            {                std::cout << " ?! it's wrong!!\n\n";            }            break;        }    }    system( "pause" );}
复制代码
注意:需在 属性页->常规->C++语言标准 中设定“预览 - 最新 C++ 工作草案中的功能 (std:c++latest)”才能编译

其运行结果如下:
  1. before compare: a=1 b=1after  compare: a=2 b=2std::max( a++, b++ ) = 2after  std::max: a=3 b=3before compare: a=1 b=2after  compare: a=3 b=4std::max( a++, b++ ) = 4after  std::max: a=4 b=5-------------------------compare: v1{ 1, 2, 3, 4, 5, 6 } <=> v2{ 1, 2, 0, 9, 0, 6 }v1[2] = 3; *p1 =4v2[2] = 0; *p2 =9v1 < v2 ?! it's wrong!!请按任意键继续. . .
复制代码
这个 bug 不仅是运算结果不对的问题,还有导致指针越界的风险,
解决的方式是:在 <=> 两端,尽量避免自增/自减等运算
不过这只是避坑而已,坑仍在那里!

这个 bug 是昨天上午发现的,当时版本是 VS2019 16.4.6;
今早微软对它进行了更新,版本为 16.5.0;
但刚才测试了下,该 bug 依然存在。
回复

使用道具 举报

0

主题

192

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-11-1 09:15:50 | 显示全部楼层
软件能不升级就不升级,能干活第一,新版本的软件,基本就是拿别人当小白鼠,
软件追求稳定能干活第一!
回复

使用道具 举报

0

主题

185

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-11-1 09:16:42 | 显示全部楼层
你不是开发者,不要来掺乎;拿别人做小白鼠,看是源于态度还是做事严谨性,至少微软不是,我也不是。
我发这个帖子,只是为了提醒其他人的。
回复

使用道具 举报

0

主题

200

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-11-1 09:17:01 | 显示全部楼层
虽然我不是开发者,但是我也经常码代码呀!
新版本的软件就是拿别人当小白鼠,微软出新操作系统都是
先发个版本出来,拿别人当小白鼠的,
活的时间长了,我现在变保守了,用的程序软件,
能不升级就不升级,程序软件,能稳定地干活,才是第一选择!
新功能永远最多只能排第二位!
回复

使用道具 举报

0

主题

194

帖子

170

积分

关内侯

Rank: 2

积分
170
发表于 2023-11-1 09:17:16 | 显示全部楼层
mathematica倒是真的有bug,
https://bbs.emath.ac.cn/forum.ph ... 977&fromuid=865
回复

使用道具 举报

0

主题

212

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-11-1 09:17:39 | 显示全部楼层
几乎所有人都同意,c++是最复杂的语言.c++20相对于c++98,几乎就是一门新语言.因为其复杂,学习成本太大,大量C++项目是基于旧的标准编写的,特别是一些历史项目.另外,因为其复杂,图书的更新也比较慢.目前,别说是c++17,c++19方面的书了,就是将c++11的图书也没几本.语言的标准,不建议使用最新的.对于最新的标准,编译器支持的一般比较有限,换个编译器,可能就出问题.目前,我公司推荐用C++11标准.太新的标准,学习起来真的吃不消.
回复

使用道具 举报

0

主题

185

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 2023-11-1 09:18:15 | 显示全部楼层
我觉得 C++ 标准进化最大的版本是 C++11,当然其经历的时间跨度也最大,之后的只是增补一些标准,使之更方便。
由于近几年标准更新得比较快,图书相对会跟不上;但可通过阅读相关的技术标准网站,还是能迅速跟上的。

以前要重载比较运算符有六种(<,<=,>,>=,==,!=);用新标准后,仅需重载两个即可:(<=>, == )
一般来说,用新的标准写代码,代码可以更优雅更自然更易读,可提效防低级失误,这何尝不是一种生产力?
当然,对于新生事物,也要保持一点警惕之心,需多加测试。
回复

使用道具 举报

0

主题

190

帖子

18

积分

新手上路

Rank: 1

积分
18
发表于 2023-11-1 09:18:28 | 显示全部楼层
我的人生经验就是:能不升级就不升级!
就像地球的地转轴的角度发生了改变的话,地球的气候又将发生变化,
人一旦习惯了过去的版本,再去习惯新版本很啰嗦,
我以前不明白老同志用的CAD为什么那么落后,
后来阅历增加,渐渐明白了,适应新的版本需要一个过程,
还可能面临着种种插件不兼容的问题,而人已经习惯了旧版本,
所以能稳定地干活才是硬道理!
回复

使用道具 举报

0

主题

171

帖子

2

积分

新手上路

Rank: 1

积分
2
发表于 2023-11-1 09:18:47 | 显示全部楼层
像vim这种软件,升级后,有时候特性就变化了,
配置文件都改变了
回复

使用道具 举报

0

主题

166

帖子

33

积分

新手上路

Rank: 1

积分
33
发表于 2023-11-1 09:19:35 | 显示全部楼层
我现在写脚本,都注明是什么操作系统,64位还是32位,运行的软件是什么版本,等等,
就怕升级后找不到原来的版本。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|hrefspace

GMT+8, 2024-11-24 08:39 , Processed in 0.073773 second(s), 21 queries .

Powered by hrefspace X3.4 Licensed

Copyright © 2022, hrefspace.

快速回复 返回顶部 返回列表