C_and_CPP 板


LINE

※ 引述《CaliforCat (Cal)》之铭言: : int main() : { : int A[3] = {0, 0, 0}; : int x = 1; : A[x++] = --x; : printf("A[0]=%d, A[1]=%d, A[2]=%d", A[0], A[1], A[2]); : } 刚好藉这个机会分享遇到 UB (undefined behavior) 的原因, 以及 该如何减少 UB 带来的冲击. 後面会提到程式理解 (program unde- rstanding) 的观念, 有兴趣可以找相关文献阅读. C/C++程式是跑在抽象机器 (abstract machine) 上的 (一种只存在 想像中的机器), 语言设计上只规范了抽象机器的行为, 并要求编译 器输出在实体机器上的执行结果要和抽象机器一致. Abstract Machine | Physical Machine C Program Program ┌────────┐ ┌────────┐ | statement #1 | │ statement #1 │ │ ↓ ←──┼─(✓ )─┼─── ↓ │ │ statement #2 │ │ statement #2 │ │ ↓ │ │ ↓ │ │ statement #3 │ │ statement #3 │ │ ↓ ←──┼─(✓ )─┼─── ↓ │ │ statement #4 │ │ statement #4 │ └────────┘ └────────┘ 一个合格的编译器, 其产生的程式的 side effect, 都会和抽象机 器相同; 但也有些地方为了兼容计算能力较差的机器, 或是保留优 化的弹性, 语言并不会明确定义这时候抽象机器的行为, 所以才有 了 UB. 初学者可能因为不熟悉抽象机器的性质, 写出依赖特定实体 机器结果, 但行为却是 UB 的程式码. 遇到 UB 不是罪过, 但要意 识到切换编译器或实体机器可能带来的行为转变. 虽然抽象机器这个概念太虚无飘渺, 但不管是开发人员还是维护人 员, 他们日常生活中都有个逼近抽象机器, 建立认知模型 (cognit- ive model), 并拿它来预测程式行为的过程. 维护人员的认知模型 与开发人员的相同, 除错效率就高; 若两者都有和抽象机器对齐, , 将程式移植到不同平台时遇到的意外就少. Cognitive Model | Physical Machine C Program Program ┌────────┐ ┌────────┐ | statement #1 | │ statement #1 │ │ ↓ │ │ ↓ │ │ statement #2 │ │ statement #2 │ │ ↓ │ │ ↓ │ │ statement #3 │ │ statement #3 │ │ ↓ │ │ ↓ │ │ statement #4 │ │ statement #4 │ └────────┘ └────────┘ 不过在大部分的情况下, 开发人员撰码时都不会将这个认知模型给 储存起来, 维护人员常需要透过逐步执行等方式将模型重建回来. 结果就是我们不仅不清楚程式实际的行为是什麽, 连预期该有的行 为也不晓得 (连结断掉了). 一旦有了认知模型, 拿它和编译出来的结果比对, 我们就容易检验 前者有没有和抽象机器对齐, 判断是否写出可携的程式码. 就我所 知描述认知模型最经济的方式是使用 contract programming, 我接 着会重建你程式码里的认知模型, 顺便演示作静态分析的思维. int A[3] = {0, 0, 0}; size_t x = 1; 在阵列 A 定义的同时也描述了任何透过 A 名称的索引值必须在 [0, 2] 区间内, 而且索引值如果用变数储存, 它的型别应该是 size_t, 为了减少错误发生我们不仅应该使用合理的值, 也应该使 用合理的型别 (以语言习惯优先) 接着我们不仅要检查 x 的值作为索引合不合法, 也要检查它作为 size_t 有没有因为运算发生 wrap-around: assert(x < SIZE_MAX); const size_t index = x++; assert(index < 3); 然後在将 x 转成 int 指派给阵列 A 元素前也要验证合法性: assert((x - 1) <= INT_MAX); const int value = (int) (--x); assert(0 <= value); 最後把程式码重新整理一下: int A[3] = {0, 0, 0}; size_t x = 1; // (1) assert(x < SIZE_MAX); const size_t index = x++; assert(index < 3); // (2) assert((x - 1) <= INT_MAX); const int value = (int) (--x); assert(0 <= value); // (3) A[index] = value; assert(A[1] == 1); // our expectation 把 (1) 和 (2) 分开写可以看到 index 和 value 变数求值的顺序 会影响结果, 导致最後的 assert() 行为改变. 那我们需不需要把 程式码改成像上面一样? 或至少把 assert() 移除? 答案是不需要 (除非你有洁癖), 但至少要保留最後的 assert(): int A[3] = {0, 0, 0}; int x = 1; A[x++] = --x; assert(A[1] == 1); // our expectation 然後当你下次执行时触发 assertion failure, 就是踩到所谓的 UB, 或 implementation-defined behavior 等预期以外的行为, 到时候 再来修改程式码即可. UB 非常多, 实务上无法靠死背来避开它们, 但你至少得知道自己的 假设还有对程式行为的预期. 藉由编译器的帮忙, 就可以知道想法 离抽象机器有多远, 再来慢慢修正认知模型. -- [P1389R1] Standing Document for SG20: Guidelines for Teaching C++ to Beginners https://wg21.link/p1389r1 SG20 Education and Recommended Videos for Teaching C++ https://www.cjdb.com.au/sg20-and-videos --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 118.233.156.253 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1631280927.A.1ED.html
1F:推 Lipraxde: 这样写 code 太严格了 Orz 09/11 00:15
※ 编辑: loveme00835 (118.233.156.253 台湾), 09/11/2021 18:33:17
2F:推 howareuuu: 推 09/20 18:52







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:iOS站内搜寻

TOP